From abb8ef4d14e42c48cbdbbfd9982daeae75442115 Mon Sep 17 00:00:00 2001
From: Gabriel Fedel <gabriel.fedel@ess.eu>
Date: Fri, 1 Apr 2022 14:37:24 +0200
Subject: [PATCH] Make the tables readback be updated automatically if they
 change

Now when a control table is changed the readback is updated automatically
on each pulse.
---
 db/sis8300llrf-Main-ControlTable-CH.template |  2 +
 src/sis8300llrfControlTableChannel.cpp       | 45 ++++++++++++++++++++
 src/sis8300llrfControlTableChannel.h         |  2 +
 3 files changed, 49 insertions(+)

diff --git a/db/sis8300llrf-Main-ControlTable-CH.template b/db/sis8300llrf-Main-ControlTable-CH.template
index 9c5ce9c5..621df350 100644
--- a/db/sis8300llrf-Main-ControlTable-CH.template
+++ b/db/sis8300llrf-Main-ControlTable-CH.template
@@ -189,6 +189,7 @@ record(waveform, "$(P)$(R)$(CTRL_TABLE_TYPE)Tbl$(SM=)-I-RB") {
     field(NELM, "$(TABLE_SMNM_MAX)")
     field(STAT, "NO_ALARM")
     field(SEVR, "NO_ALARM")
+    field(SCAN, "I/O Intr")
 
     info(DESCRIPTION, "Get the I control table.")
     info(SYSTEM,	"LLRF")
@@ -202,6 +203,7 @@ record(waveform, "$(P)$(R)$(CTRL_TABLE_TYPE)Tbl$(SM=)-Q-RB") {
     field(NELM, "$(TABLE_SMNM_MAX)")
     field(STAT, "NO_ALARM")
     field(SEVR, "NO_ALARM")
+    field(SCAN, "I/O Intr")
 
     info(DESCRIPTION, "Get the Q control table.")
     info(SYSTEM,	"LLRF")
diff --git a/src/sis8300llrfControlTableChannel.cpp b/src/sis8300llrfControlTableChannel.cpp
index 88658d89..e1879e41 100644
--- a/src/sis8300llrfControlTableChannel.cpp
+++ b/src/sis8300llrfControlTableChannel.cpp
@@ -90,6 +90,7 @@ sis8300llrfControlTableChannel::sis8300llrfControlTableChannel() :
     _TableSpeed = 0;
     _ConstantEnable = 0;
     _Initialized = 0;
+    _TableChange = 0;
 
     _writeTableLoopTaskRun = 1;
     std::string taskname = "writeTableLoopTask";
@@ -512,6 +513,8 @@ ndsStatus sis8300llrfControlTableChannel::writeTableLoopTask(nds::TaskServiceBas
                 //NDS_DBG("Perf to load table: %f\n", perf);
                 doCallbacksInt32(0, _interruptIdWriteTable);
                 _WriteTable = 0;
+                // let IOC know that the table changed, so the readback will be updated on next pulse
+                _TableChange = 1;
             }
         usleep(10);
     }
@@ -534,6 +537,48 @@ ndsStatus sis8300llrfControlTableChannel::writeToHardware(){
         dynamic_cast<sis8300llrfControlTableChannelGroup*> 
             (getChannelGroup());
 
+    //If the table changed reload the read back
+    if (_TableChange){
+        _TableChange = 0;
+        NDS_TRC("Reload tables readback");
+        
+        //This temporary pointer is used to load the data from memory
+        epicsFloat64 *tmp = new epicsFloat64[_MaxSamplesCount];
+
+        /* I and Q tables are interleaved. We fetch them as on table with
+         * 32 bit ellements from the device and than read it as two 16 bit
+         * tables */
+        epicsInt16 *pInt16Buffer = (epicsInt16 *) tmp;
+        int iterSrc, iterDest;
+
+        if (getCurrentState() == nds::CHANNEL_STATE_IOC_INITIALIZATION) {
+            delete[] tmp;
+            return ndsError;
+        }
+        
+        status = sis8300llrfdrv_get_ctrl_table_raw(
+                _DeviceUser, _CtrlTableType, 
+                ROUNDUP_TWOHEX(_SamplesCount), (epicsInt32 *)tmp);
+        SIS8300NDS_STATUS_CHECK("sis8300llrfdrv_get_ctrl_table_raw", status);
+
+        epicsFloat64 *I = new epicsFloat64[_SamplesCount];
+        epicsFloat64 *Q = new epicsFloat64[_SamplesCount];
+
+        for(iterDest = 0, iterSrc = 0; 
+                iterDest < _SamplesCount; iterDest++, iterSrc += 2) {
+            I[iterDest] =( (epicsFloat64) pInt16Buffer[iterSrc+SIS8300LLRFDRV_RAW_SAMPLE_I_OFFSET] )/ _FFSPConvFact;
+            Q[iterDest] =( (epicsFloat64) pInt16Buffer[iterSrc+SIS8300LLRFDRV_RAW_SAMPLE_Q_OFFSET] )/ _FFSPConvFact;
+        }
+
+        //push values to the PVs
+        doCallbacksFloat64Array(I, _SamplesCount, _interruptIdITable);
+        doCallbacksFloat64Array(Q, _SamplesCount, _interruptIdQTable);
+
+        delete[] tmp;
+        delete[] I;
+        delete[] Q;
+    }
+
     if (_TableModeChange) {
         _TableModeChange = 0;
 
diff --git a/src/sis8300llrfControlTableChannel.h b/src/sis8300llrfControlTableChannel.h
index a40c707d..b3f89716 100644
--- a/src/sis8300llrfControlTableChannel.h
+++ b/src/sis8300llrfControlTableChannel.h
@@ -111,6 +111,8 @@ protected:
 
     int        _WriteTable;         /**< Parameter to trigger write
                                       * of tables */
+    int        _TableChange;        /** < Parameter tracking Table 
+                                      * change */
     int        _SamplesCountChange; /** < Parameter Tracking Samples 
                                       * count changes */
     int        _TableModeChange;  /** < Parameter tracking Table 
-- 
GitLab