From e1c7216e2bbc774d8f8ddfe4abc9b41f1f16f0cd Mon Sep 17 00:00:00 2001
From: marcofilho <marco.filho@ess.eu>
Date: Mon, 15 Jul 2024 15:32:15 +0200
Subject: [PATCH] Use map to organize registers. Add SC register.

This commit organizes all possible register parameter lists in a map.

This is so findRegister can search each register map from a single data structure
instead of having to hardcode every new register parameter list in the findRegister function.

Now, to add a new register, developer should only need to:

  1 - Create the register parameter list and add it to the map in vmm_tbl.h:39-41
  2 - ... I think that's it(?)

Also, asynPrint should tell which hybrid, vmm and register are being affected by the operation now.
---
 vmmTblApp/Db/channels.sub |  5 ++++
 vmmTblApp/src/vmm_tbl.cpp | 55 ++++++++++++++++++++++++---------------
 vmmTblApp/src/vmm_tbl.h   |  7 +++--
 3 files changed, 44 insertions(+), 23 deletions(-)

diff --git a/vmmTblApp/Db/channels.sub b/vmmTblApp/Db/channels.sub
index c7c4221..d0be700 100644
--- a/vmmTblApp/Db/channels.sub
+++ b/vmmTblApp/Db/channels.sub
@@ -4,4 +4,9 @@ pattern {HYB, VMM, CH}
         {0,   1,  "ST"}
         {1,   0,  "ST"}
         {1,   1,  "ST"}
+
+        {0,   0,  "SC"}
+        {0,   1,  "SC"}
+        {1,   0,  "SC"}
+        {1,   1,  "SC"}
 }
diff --git a/vmmTblApp/src/vmm_tbl.cpp b/vmmTblApp/src/vmm_tbl.cpp
index d66fb43..a8d4ef2 100644
--- a/vmmTblApp/src/vmm_tbl.cpp
+++ b/vmmTblApp/src/vmm_tbl.cpp
@@ -56,6 +56,9 @@ asynStatus VMMTbl::createEpicsParams() {
     param_name.str("");
     param_name << "HYB_" << hyb <<"_" << vmm << "_ST";
     pRMM->createParam(addr_list, param_name.str().c_str(), asynParamInt8Array, &vmmST_[hyb][vmm]);
+    param_name.str("");
+    param_name << "HYB_" << hyb <<"_" << vmm << "_SC";
+    pRMM->createParam(addr_list, param_name.str().c_str(), asynParamInt8Array, &vmmSC_[hyb][vmm]);
     }
   }
 
@@ -108,48 +111,58 @@ asynStatus VMMTbl::writeInt8Array(asynUser *pasynUser, epicsInt8 *value, size_t
   int ncopy = CHANNELS_PER_VMM;
   const char *paramName;
   const char *functionName = "writeInt8Array";
-  asynStatus status = asynSuccess;
+  int status = asynSuccess;
   std::vector<epicsInt8> int8Array;
-  Pair pair;
+  Reg pair;
 
-  status = pRMM->parseAsynUser(pasynUser, &function, &addr, &paramName);
-  if (status != asynSuccess) return status;
-
-  pair = findPair(function, vmmST_);
+  status |= pRMM->parseAsynUser(pasynUser, &function, &addr, &paramName);
   pRMM->getParamName(addr, function, &paramName);
+  status |= findRegister(function, &pair);
+  if (status) return (asynStatus) status;
 
   asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
-            "%s:%s: function=%d, name=%s, value=%d, hybrid=%d, vmm=%d\n",
-            driverName, functionName, function, paramName, value, pair.hyb, pair.vmm);
+            "%s:%s: function=%d, name=%s, value=%d, hybrid=%d, vmm=%d, register=%s\n",
+            driverName, functionName, function, paramName, value, pair.hyb, pair.vmm, pair.rg.c_str());
 
   for (epicsInt8 i = 0; i < ncopy; ++i) {
     int8Array.push_back(static_cast<int>(value[i]) >= 1 ? 1 : 0);
-    pVMMConfig.getHybrid(pair.hyb).getVMM(pair.vmm).setRegister("st",
+    pVMMConfig.getHybrid(pair.hyb).getVMM(pair.vmm).setRegister(pair.rg.c_str(),
                                                   static_cast<int>(value[i]),
                                                   i);
   }
 
-  status = pRMM->doCallbacksInt8Array(int8Array.data(), int8Array.size(), function, 0);
-  return status;
+  status |= pRMM->doCallbacksInt8Array(int8Array.data(), int8Array.size(), function, 0);
+  return (asynStatus) status;
 
 }
 
-Pair VMMTbl::findPair(int function, int array[HYBRIDS_PER_FEN][VMMS_PER_HYBRID]){
+asynStatus VMMTbl::findRegister(int function, Reg *reg_){
 
-  Pair ret;
+  int (*array)[VMMS_PER_HYBRID];
+  std::map<std::string, int(*)[VMMS_PER_HYBRID]>::iterator it;
 
-  for (int h = 0; h < number_hybrids; h++){
-    for (int v = 0; v < VMMS_PER_HYBRID; v++)
-    {
-      if (array[h][v] == function){
-        ret.hyb = h;
-        ret.vmm = v;
-        return ret;
+  it = this->registers.begin();
+
+  while ( it != this->registers.end() ){
+    std::string reg_name = it->first;
+    array = registers[reg_name];
+
+    for (int h = 0; h < number_hybrids; h++){
+      for (int v = 0; v < VMMS_PER_HYBRID; v++)
+      {
+        if (array[h][v] == function){
+          reg_->hyb = h;
+          reg_->vmm = v;
+          reg_->rg = reg_name;
+          return asynSuccess;
+        }
       }
     }
+
+    it++;
   }
 
-  return ret;
+  return asynError;
 
 }
 
diff --git a/vmmTblApp/src/vmm_tbl.h b/vmmTblApp/src/vmm_tbl.h
index 325337f..8e2a64c 100644
--- a/vmmTblApp/src/vmm_tbl.h
+++ b/vmmTblApp/src/vmm_tbl.h
@@ -6,9 +6,10 @@
 #include "vmm_config.h"
 
 /* Struct to hold Hyb, VMM pair values */
-struct Pair {
+struct Reg {
   int hyb = -1;
   int vmm = -1;
+  std::string rg = "\0";
 };
 
 /** Class definition for the VMMTbl class */
@@ -21,7 +22,7 @@ public:
   virtual asynStatus writeInt8Array(asynUser *pasynUser, epicsInt8 *value, size_t nElements);
   void setInitialEpicsParams();
   void configFE();
-  Pair findPair(int function, int array[HYBRIDS_PER_FEN][VMMS_PER_HYBRID]);
+  asynStatus findRegister(int function, Reg *reg_);
 
 protected:
   int vmmSelectMonitorVMM0_;
@@ -36,6 +37,8 @@ protected:
   int vmmHybLinkStatus_[HYBRIDS_PER_FEN];
   //Registers channels per hybrid, per VMM
   int vmmST_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID];
+  int vmmSC_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID];
+  std::map<std::string, int(*)[VMMS_PER_HYBRID]> registers{{"ST", vmmST_}, {"SC", vmmSC_}};
 
 private:
   static constexpr const char *driverName = "VMMTbl";
-- 
GitLab