From 8e40b8b0ffc8e4421fc62db3d2fa7ee5666254a7 Mon Sep 17 00:00:00 2001
From: Juliano Murari <juliano.murari@ess.eu>
Date: Mon, 19 Sep 2022 13:44:30 +0200
Subject: [PATCH] PBIBCM-228 Add auxiliary Upper/Lower/Hysteresis Threshold PVs

---
 sis8300bcmApp/Db/sis8300bcm-acct.template | 60 +++++++++++++++
 sis8300bcmApp/src/sis8300bcm.cpp          | 39 ++++++++++
 sis8300bcmApp/src/sis8300bcm.h            |  6 ++
 vendor/ess/lib/sis8300bcm_reg.h           |  3 +
 vendor/ess/lib/sis8300drvbcm.c            | 90 +++++++++++++++++++++++
 vendor/ess/lib/sis8300drvbcm.h            |  6 ++
 6 files changed, 204 insertions(+)

diff --git a/sis8300bcmApp/Db/sis8300bcm-acct.template b/sis8300bcmApp/Db/sis8300bcm-acct.template
index 38ec984..acf5e6d 100644
--- a/sis8300bcmApp/Db/sis8300bcm-acct.template
+++ b/sis8300bcmApp/Db/sis8300bcm-acct.template
@@ -1173,6 +1173,66 @@ record(ai, "$(P)$(R)CalibrationSample4R")
     field(SCAN, "I/O Intr")
 }
 
+record(ao, "$(P)$(R)AuxUpperThreshold")
+{
+    field(DTYP, "asynFloat64")
+    field(OUT,  "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))BCM.ACCT.AUX_UPPER_THRESHOLD")
+    field(EGU,  "V")
+    field(PREC, "4")
+    field(DRVH, "1.0")
+    field(DRVL, "-1.0")
+    field(ASG,  "critical")
+    info(autosaveFields, "VAL")
+}
+record(ai, "$(P)$(R)AuxUpperThresholdR")
+{
+    field(DTYP, "asynFloat64")
+    field(INP,  "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))BCM.ACCT.AUX_UPPER_THRESHOLD")
+    field(EGU,  "V")
+    field(PREC, "4")
+    field(SCAN, "I/O Intr")
+}
+
+record(ao, "$(P)$(R)AuxLowerThreshold")
+{
+    field(DTYP, "asynFloat64")
+    field(OUT,  "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))BCM.ACCT.AUX_LOWER_THRESHOLD")
+    field(EGU,  "V")
+    field(PREC, "4")
+    field(DRVH, "1.0")
+    field(DRVL, "-1.0")
+    field(ASG,  "critical")
+    info(autosaveFields, "VAL")
+}
+record(ai, "$(P)$(R)AuxLowerThresholdR")
+{
+    field(DTYP, "asynFloat64")
+    field(INP,  "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))BCM.ACCT.AUX_LOWER_THRESHOLD")
+    field(EGU,  "V")
+    field(PREC, "4")
+    field(SCAN, "I/O Intr")
+}
+
+record(ao, "$(P)$(R)AuxHysteresisThreshold")
+{
+    field(DTYP, "asynFloat64")
+    field(OUT,  "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))BCM.ACCT.AUX_HYSTERESIS_THRESHOLD")
+    field(EGU,  "V")
+    field(PREC, "4")
+    field(DRVH, "1.0")
+    field(DRVL, "-1.0")
+    field(ASG,  "critical")
+    info(autosaveFields, "VAL")
+}
+record(ai, "$(P)$(R)AuxHysteresisThresholdR")
+{
+    field(DTYP, "asynFloat64")
+    field(INP,  "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))BCM.ACCT.AUX_HYSTERESIS_THRESHOLD")
+    field(EGU,  "V")
+    field(PREC, "4")
+    field(SCAN, "I/O Intr")
+}
+
 record(ao, "$(P)$(R)BeamOverThreshold")
 {
     field(DTYP, "asynFloat64")
diff --git a/sis8300bcmApp/src/sis8300bcm.cpp b/sis8300bcmApp/src/sis8300bcm.cpp
index ca6142e..fce8414 100644
--- a/sis8300bcmApp/src/sis8300bcm.cpp
+++ b/sis8300bcmApp/src/sis8300bcm.cpp
@@ -267,6 +267,9 @@ sis8300bcm::sis8300bcm(const char *portName, const char *devicePath,
     createParam(BCMAcctCalibrationSample2String,            asynParamFloat64,   &BCMAcctCalibrationSample2);
     createParam(BCMAcctCalibrationSample3String,            asynParamFloat64,   &BCMAcctCalibrationSample3);
     createParam(BCMAcctCalibrationSample4String,            asynParamFloat64,   &BCMAcctCalibrationSample4);
+    createParam(BCMAcctAuxUpperThresholdString,             asynParamFloat64,   &BCMAcctAuxUpperThreshold);
+    createParam(BCMAcctAuxLowerThresholdString,             asynParamFloat64,   &BCMAcctAuxLowerThreshold);
+    createParam(BCMAcctAuxHysteresisThresholdString,        asynParamFloat64,   &BCMAcctAuxHysteresisThreshold);
     createParam(BCMAcctBeamAboveThresholdString,            asynParamFloat64,   &BCMAcctBeamAboveThreshold);
     createParam(BCMAcctLeakyCoefficientString,              asynParamFloat64,   &BCMAcctLeakyCoefficient);
     createParam(BCMAcctLeakyThresholdString,                asynParamFloat64,   &BCMAcctLeakyThreshold);
@@ -905,6 +908,27 @@ int sis8300bcm::readbackParameters()
         }
         setDoubleParam(addr, BCMAcctCalibrationSample4, doubleValue);
 
+        ret = sis8300drvbcm_get_channel_aux_upper_threshold(mDeviceHandle, addr, &doubleValue);
+        if (ret) {
+            asynPrintError(pasynUserSelf, "sis8300drvbcm_get_channel_aux_upper_threshold returned %d", ret);
+            return ret;
+        }
+        setDoubleParam(addr, BCMAcctAuxUpperThreshold, doubleValue);
+
+        ret = sis8300drvbcm_get_channel_aux_lower_threshold(mDeviceHandle, addr, &doubleValue);
+        if (ret) {
+            asynPrintError(pasynUserSelf, "sis8300drvbcm_get_channel_aux_lower_threshold returned %d", ret);
+            return ret;
+        }
+        setDoubleParam(addr, BCMAcctAuxLowerThreshold, doubleValue);
+
+        ret = sis8300drvbcm_get_channel_aux_hysteresis_threshold(mDeviceHandle, addr, &doubleValue);
+        if (ret) {
+            asynPrintError(pasynUserSelf, "sis8300drvbcm_get_channel_aux_hysteresis_threshold returned %d", ret);
+            return ret;
+        }
+        setDoubleParam(addr, BCMAcctAuxHysteresisThreshold, doubleValue);
+
         ret = sis8300drvbcm_get_channel_beam_above_threshold(mDeviceHandle, addr, &doubleValue);
         if (ret) {
             asynPrintError(pasynUserSelf, "sis8300drvbcm_get_channel_beam_above_threshold returned %d", ret);
@@ -2111,6 +2135,21 @@ asynStatus sis8300bcm::writeFloat64(asynUser *pasynUser, epicsFloat64 value)
         if (ret) {
             asynPrintError(pasynUser, "sis8300drvbcm_set_channel_errant_window_end returned %d", ret);
         }
+    } else if (function == BCMAcctAuxUpperThreshold) {
+        ret = sis8300drvbcm_set_channel_aux_upper_threshold(mDeviceHandle, addr, value);
+        if (ret) {
+            asynPrintError(pasynUser, "sis8300drvbcm_set_channel_aux_upper_threshold returned %d", ret);
+        }
+    } else if (function == BCMAcctAuxLowerThreshold) {
+        ret = sis8300drvbcm_set_channel_aux_lower_threshold(mDeviceHandle, addr, value);
+        if (ret) {
+            asynPrintError(pasynUser, "sis8300drvbcm_set_channel_aux_lower_threshold returned %d", ret);
+        }
+    } else if (function == BCMAcctAuxHysteresisThreshold) {
+        ret = sis8300drvbcm_set_channel_aux_hysteresis_threshold(mDeviceHandle, addr, value);
+        if (ret) {
+            asynPrintError(pasynUser, "sis8300drvbcm_set_channel_aux_hysteresis_threshold returned %d", ret);
+        }
     } else if (function == BCMAcctBeamAboveThreshold) {
         asynPrintDeviceInfo(pasynUserSelf, "set_channel_beam_above_threshold: addr %d, value %f", addr, value);
         ret = sis8300drvbcm_set_channel_beam_above_threshold(mDeviceHandle, addr, value);
diff --git a/sis8300bcmApp/src/sis8300bcm.h b/sis8300bcmApp/src/sis8300bcm.h
index d5aadba..a4e9df6 100644
--- a/sis8300bcmApp/src/sis8300bcm.h
+++ b/sis8300bcmApp/src/sis8300bcm.h
@@ -163,6 +163,9 @@
 #define BCMAcctCalibrationSample2String              "BCM.ACCT.CALIBRATION_SAMPLE2"
 #define BCMAcctCalibrationSample3String              "BCM.ACCT.CALIBRATION_SAMPLE3"
 #define BCMAcctCalibrationSample4String              "BCM.ACCT.CALIBRATION_SAMPLE4"
+#define BCMAcctAuxUpperThresholdString               "BCM.ACCT.AUX_UPPER_THRESHOLD"
+#define BCMAcctAuxLowerThresholdString               "BCM.ACCT.AUX_LOWER_THRESHOLD"
+#define BCMAcctAuxHysteresisThresholdString          "BCM.ACCT.AUX_HYSTERESIS_THRESHOLD"
 #define BCMAcctBeamAboveThresholdString              "BCM.ACCT.BEAM_ABOVE_THRESHOLD"
 #define BCMAcctLeakyCoefficientString                "BCM.ACCT.LEAKY_INTEGRATOR_COEFFICIENT"
 #define BCMAcctLeakyThresholdString                  "BCM.ACCT.LEAKY_INTEGRATOR_THRESHOLD"
@@ -387,6 +390,9 @@ protected:
     int BCMAcctCalibrationSample2;
     int BCMAcctCalibrationSample3;
     int BCMAcctCalibrationSample4;
+    int BCMAcctAuxUpperThreshold;
+    int BCMAcctAuxLowerThreshold;
+    int BCMAcctAuxHysteresisThreshold;
     int BCMAcctBeamAboveThreshold;
     int BCMAcctLeakyCoefficient;
     int BCMAcctLeakyThreshold;
diff --git a/vendor/ess/lib/sis8300bcm_reg.h b/vendor/ess/lib/sis8300bcm_reg.h
index 4cec2b9..b307372 100644
--- a/vendor/ess/lib/sis8300bcm_reg.h
+++ b/vendor/ess/lib/sis8300bcm_reg.h
@@ -146,6 +146,9 @@ extern "C" {
 #define SIS8300BCM_ACCT_X_LEAKY_THR_REG                 0x02E
 #define SIS8300BCM_ACCT_X_FLATTOP_RISING_OFF            0x02F
 #define SIS8300BCM_ACCT_X_FLATTOP_FALLING_OFF           0x030
+#define SIS8300BCM_ACCT_X_AUX_UPPER_THRESHOLD_OFF       0x031
+#define SIS8300BCM_ACCT_X_AUX_LOWER_THRESHOLD_OFF       0x032
+#define SIS8300BCM_ACCT_X_AUX_HYSTERESIS_THRESHOLD_OFF  0x033
 #define SIS8300BCM_ACCT_X_BEAM_ABOVE_THRESHOLD_REG      0x034
 #define SIS8300BCM_ACCT_X_TRIGGER_WIDTH_OFF             0x035
 #define SIS8300BCM_ACCT_X_AUTO_FLATTOP_RISING_OFF       0x036
diff --git a/vendor/ess/lib/sis8300drvbcm.c b/vendor/ess/lib/sis8300drvbcm.c
index cad884e..7e51093 100644
--- a/vendor/ess/lib/sis8300drvbcm.c
+++ b/vendor/ess/lib/sis8300drvbcm.c
@@ -2762,6 +2762,96 @@ int sis8300drvbcm_set_enable_calibration_pulse(sis8300drv_usr *sisuser, unsigned
     return ret;
 }
 
+// used to control aux upper threshold
+int sis8300drvbcm_set_channel_aux_upper_threshold(sis8300drv_usr *sisuser, unsigned int channel, double threshold)
+{
+    unsigned int reg = SIS8300BCM_CHANNEL_BLOCK_BASE + \
+                        (SIS8300BCM_CHANNEL_BLOCK_SIZE * channel) + \
+                        SIS8300BCM_ACCT_BANK_OFF + \
+                        SIS8300BCM_ACCT_X_AUX_UPPER_THRESHOLD_OFF;
+    // register takes a signed value
+    int value = (int)(threshold * 32768);
+    // printf("%s: channel %d, reg 0x%x, value: %d\n", __func__, channel, reg, value);
+    return sis8300drv_reg_write(sisuser, reg, value);
+}
+
+int sis8300drvbcm_get_channel_aux_upper_threshold(sis8300drv_usr *sisuser, unsigned int channel, double *threshold)
+{
+    unsigned int reg = SIS8300BCM_CHANNEL_BLOCK_BASE + \
+                        (SIS8300BCM_CHANNEL_BLOCK_SIZE * channel) + \
+                        SIS8300BCM_ACCT_BANK_OFF + \
+                        SIS8300BCM_ACCT_X_AUX_UPPER_THRESHOLD_OFF;
+    // register holds a signed value
+    int value;
+    int ret = sis8300drv_reg_read(sisuser, reg, (unsigned *)&value);
+    if (ret) {
+        return ret;
+    }
+    *threshold = (value / 32768.0);
+    // printf("%s: channel %d, reg 0x%x, value: %d\n", __func__, channel, reg, value);
+    return ret;
+}
+
+// used to control aux lower threshold
+int sis8300drvbcm_set_channel_aux_lower_threshold(sis8300drv_usr *sisuser, unsigned int channel, double threshold)
+{
+    unsigned int reg = SIS8300BCM_CHANNEL_BLOCK_BASE + \
+                        (SIS8300BCM_CHANNEL_BLOCK_SIZE * channel) + \
+                        SIS8300BCM_ACCT_BANK_OFF + \
+                        SIS8300BCM_ACCT_X_AUX_LOWER_THRESHOLD_OFF;
+    // register takes a signed value
+    int value = (int)(threshold * 32768);
+    // printf("%s: channel %d, reg 0x%x, value: %d\n", __func__, channel, reg, value);
+    return sis8300drv_reg_write(sisuser, reg, value);
+}
+
+int sis8300drvbcm_get_channel_aux_lower_threshold(sis8300drv_usr *sisuser, unsigned int channel, double *threshold)
+{
+    unsigned int reg = SIS8300BCM_CHANNEL_BLOCK_BASE + \
+                        (SIS8300BCM_CHANNEL_BLOCK_SIZE * channel) + \
+                        SIS8300BCM_ACCT_BANK_OFF + \
+                        SIS8300BCM_ACCT_X_AUX_LOWER_THRESHOLD_OFF;
+    // register holds a signed value
+    int value;
+    int ret = sis8300drv_reg_read(sisuser, reg, (unsigned *)&value);
+    if (ret) {
+        return ret;
+    }
+    *threshold = (value / 32768.0);
+    // printf("%s: channel %d, reg 0x%x, value: %d\n", __func__, channel, reg, value);
+    return ret;
+}
+
+// used to control aux hysteresis threshold
+int sis8300drvbcm_set_channel_aux_hysteresis_threshold(sis8300drv_usr *sisuser, unsigned int channel, double threshold)
+{
+    unsigned int reg = SIS8300BCM_CHANNEL_BLOCK_BASE + \
+                        (SIS8300BCM_CHANNEL_BLOCK_SIZE * channel) + \
+                        SIS8300BCM_ACCT_BANK_OFF + \
+                        SIS8300BCM_ACCT_X_AUX_HYSTERESIS_THRESHOLD_OFF;
+    // register takes a signed value
+    int value = (int)(threshold * 32768);
+    // printf("%s: channel %d, reg 0x%x, value: %d\n", __func__, channel, reg, value);
+    return sis8300drv_reg_write(sisuser, reg, value);
+}
+
+int sis8300drvbcm_get_channel_aux_hysteresis_threshold(sis8300drv_usr *sisuser, unsigned int channel, double *threshold)
+{
+    unsigned int reg = SIS8300BCM_CHANNEL_BLOCK_BASE + \
+                        (SIS8300BCM_CHANNEL_BLOCK_SIZE * channel) + \
+                        SIS8300BCM_ACCT_BANK_OFF + \
+                        SIS8300BCM_ACCT_X_AUX_HYSTERESIS_THRESHOLD_OFF;
+    // register holds a signed value
+    int value;
+    int ret = sis8300drv_reg_read(sisuser, reg, (unsigned *)&value);
+    if (ret) {
+        return ret;
+    }
+    *threshold = (value / 32768.0);
+    // printf("%s: channel %d, reg 0x%x, value: %d\n", __func__, channel, reg, value);
+    return ret;
+}
+
 // used to control beam above threshold
 int sis8300drvbcm_set_channel_beam_above_threshold(sis8300drv_usr *sisuser, unsigned int channel, double threshold)
 {
diff --git a/vendor/ess/lib/sis8300drvbcm.h b/vendor/ess/lib/sis8300drvbcm.h
index 9bf2903..93b3c59 100644
--- a/vendor/ess/lib/sis8300drvbcm.h
+++ b/vendor/ess/lib/sis8300drvbcm.h
@@ -211,6 +211,12 @@ int sis8300drvbcm_set_channel_errant_window_start(sis8300drv_usr *sisuser, unsig
 int sis8300drvbcm_get_channel_errant_window_start(sis8300drv_usr *sisuser, unsigned int channel, double *start);
 int sis8300drvbcm_set_channel_errant_window_end(sis8300drv_usr *sisuser, unsigned int channel, double end);
 int sis8300drvbcm_get_channel_errant_window_end(sis8300drv_usr *sisuser, unsigned int channel, double *end);
+int sis8300drvbcm_set_channel_aux_upper_threshold(sis8300drv_usr *sisuser, unsigned int channel, double threshold);
+int sis8300drvbcm_get_channel_aux_upper_threshold(sis8300drv_usr *sisuser, unsigned int channel, double *threshold);
+int sis8300drvbcm_set_channel_aux_lower_threshold(sis8300drv_usr *sisuser, unsigned int channel, double threshold);
+int sis8300drvbcm_get_channel_aux_lower_threshold(sis8300drv_usr *sisuser, unsigned int channel, double *threshold);
+int sis8300drvbcm_set_channel_aux_hysteresis_threshold(sis8300drv_usr *sisuser, unsigned int channel, double threshold);
+int sis8300drvbcm_get_channel_aux_hysteresis_threshold(sis8300drv_usr *sisuser, unsigned int channel, double *threshold);
 int sis8300drvbcm_set_channel_beam_above_threshold(sis8300drv_usr *sisuser, unsigned int channel, double threshold);
 int sis8300drvbcm_get_channel_beam_above_threshold(sis8300drv_usr *sisuser, unsigned int channel, double *threshold);
 int sis8300drvbcm_get_channel_trigger_width(sis8300drv_usr *sisuser, unsigned int channel, double *width);
-- 
GitLab