diff --git a/vmmTbl.Makefile b/vmmTbl.Makefile
index 585f59a18bcf9fabf39a65850bd2db8a727813f3..4654223b737786a2eea95dd586d164d52cd035dc 100644
--- a/vmmTbl.Makefile
+++ b/vmmTbl.Makefile
@@ -14,6 +14,7 @@ SUBS = $(APPDB)/channels.sub
 LIB_SYS_LIBS += vmmapi
 
 SOURCES += $(APPSRC)/vmm_tbl.cpp
+SOURCES += $(APPSRC)/Utils.cpp
 
 DBDS    += $(APPSRC)/vmm_tbl.dbd
 
diff --git a/vmmTblApp/Db/channels.template b/vmmTblApp/Db/channels.template
index 4347f5bb476f29a698029146e190c85d780f9cc8..03ee4d6d3ca9db9827c22ebff8014b85aded0e5f 100644
--- a/vmmTblApp/Db/channels.template
+++ b/vmmTblApp/Db/channels.template
@@ -9,9 +9,19 @@ record(aao, "$(P)$(R)$(HYB)$(VMM)$(C)$(CH)-S") {
     field(DTYP, "asynInt8ArrayOut")
     field(NELM, "64")
     field(FTVL, "CHAR")
+    field(FLNK, "$(P)$(R)$(HYB)$(VMM)$(C)$(CH)-R")
     field(OUT,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_$(VMM)_$(CH)")
 }
 
+record(aai, "$(P)$(R)$(HYB)$(VMM)$(C)$(CH)-R") {
+    field(DESC, "Get $(CH) channels array")
+    field(DTYP, "asynInt8ArrayIn")
+    field(NELM, "64")
+    field(FTVL, "CHAR")
+    field(SCAN, "I/O Intr")
+    field(INP,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_$(VMM)_$(CH)")
+}
+
 record(bo, "$(P)$(R)$(HYB)$(VMM)$(C)All$(CH)-S") {
     field(DESC, "Set all $(CH) channels")
     field(VAL,  "0")
diff --git a/vmmTblApp/Db/hybrid.template b/vmmTblApp/Db/hybrid.template
index 323e111b4e66dd9faadf2d191f4f11baf436e5c1..27703968a02ee4a7f8d276fc93876b1b87d0bae0 100644
--- a/vmmTblApp/Db/hybrid.template
+++ b/vmmTblApp/Db/hybrid.template
@@ -2,12 +2,160 @@ record(stringin, "$(P)$(R)Hyb$(HYB)FwVersion-R") {
     field(DESC, "Hybrid $(HYB) Firmware version")
     field(DTYP, "asynOctetRead")
     field(INP,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_FW_VERSION")
+    field(PINI, "YES")
     field(SCAN, "I/O Intr")
 }
 
+record(mbbo, "$(P)$(R)Hyb$(HYB)Skew-S"){
+    field(DESC, "Hybrid's #$(HYB) Skew")
+    field(DTYP, "asynInt32")
+    field(OUT,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_SKEW")
+    field(ZRST, "0 ns")
+    field(ZRVL, "0")
+    field(ONST, "2.83921 ns")
+    field(ONVL, "1")
+    field(TWST, "5.67842 ns")
+    field(TWVL, "2")
+    field(THST, "8.51764 ns")
+    field(THVL, "3")
+    field(FRST, "11.3568 ns")
+    field(FRVL, "4")
+    field(FVST, "14.1961 ns")
+    field(FVVL, "5")
+    field(SXST, "17.0353 ns")
+    field(SXVL, "6")
+    field(SVST, "19.8545 ns")
+    field(SVVL, "7")
+    field(EIST, "22.7137 ns")
+    field(EIVL, "8")
+    field(NIST, "25.5529 ns")
+    field(NIVL, "9")
+    field(TEST, "28.3921 ns")
+    field(TEVL, "10")
+    field(ELST, "31.2313 ns")
+    field(ELVL, "11")
+    field(TVST, "34.0705 ns")
+    field(TVVL, "12")
+    field(TTST, "36.9098 ns")
+    field(TTVL, "13")
+    field(FTST, "39.749 ns")
+    field(FTVL, "14")
+    field(FFST, "42.5882 ns")
+    field(FFVL, "15")
+    field(FLNK, "$(P)$(R)Hyb$(HYB)Skew-RB")
+}
+
+record(mbbi, "$(P)$(R)Hyb$(HYB)Skew-RB"){
+    field(DESC, "Hybrid's #$(HYB) Skew")
+    field(DTYP, "asynInt32")
+    field(INP,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_SKEW")
+    field(ZRST, "0 ns")
+    field(ZRVL, "0")
+    field(ONST, "2.83921 ns")
+    field(ONVL, "1")
+    field(TWST, "5.67842 ns")
+    field(TWVL, "2")
+    field(THST, "8.51764 ns")
+    field(THVL, "3")
+    field(FRST, "11.3568 ns")
+    field(FRVL, "4")
+    field(FVST, "14.1961 ns")
+    field(FVVL, "5")
+    field(SXST, "17.0353 ns")
+    field(SXVL, "6")
+    field(SVST, "19.8545 ns")
+    field(SVVL, "7")
+    field(EIST, "22.7137 ns")
+    field(EIVL, "8")
+    field(NIST, "25.5529 ns")
+    field(NIVL, "9")
+    field(TEST, "28.3921 ns")
+    field(TEVL, "10")
+    field(ELST, "31.2313 ns")
+    field(ELVL, "11")
+    field(TVST, "34.0705 ns")
+    field(TVVL, "12")
+    field(TTST, "36.9098 ns")
+    field(TTVL, "13")
+    field(FTST, "39.749 ns")
+    field(FTVL, "14")
+    field(FFST, "42.5882 ns")
+    field(FFVL, "15")
+    field(SCAN, "I/O Intr")
+    field(PINI, "YES")
+}
+
+record(mbbo, "$(P)$(R)Hyb$(HYB)Width-S"){
+    field(DESC, "Hybrid's #$(HYB) Width")
+    field(DTYP, "asynInt32")
+    field(OUT,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_WIDTH")
+    field(ZRST, "128 x 22.7137")
+    field(ZRVL, "0")
+    field(ONST, "64 x 22.7137")
+    field(ONVL, "1")
+    field(TWST, "32 x 22.7137")
+    field(TWVL, "2")
+    field(THST, "16 x 22.7137")
+    field(THVL, "3")
+    field(FRST, "8 x 22.7137")
+    field(FRVL, "4")
+    field(FVST, "4 x 22.7137")
+    field(FVVL, "5")
+    field(SXST, "2 x 22.7137")
+    field(SXVL, "6")
+    field(SVST, "1 x 22.7137")
+    field(SVVL, "7") 
+    field(FLNK, "$(P)$(R)Hyb$(HYB)Width-RB")
+}
+
+record(mbbi, "$(P)$(R)Hyb$(HYB)Width-RB"){
+    field(DESC, "Hybrid's #$(HYB) Width")
+    field(DTYP, "asynInt32")
+    field(INP,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_WIDTH")
+    field(PINI, "YES")
+    field(ZRST, "128 x 22.7137")
+    field(ZRVL, "0")
+    field(ONST, "64 x 22.7137")
+    field(ONVL, "1")
+    field(TWST, "32 x 22.7137")
+    field(TWVL, "2")
+    field(THST, "16 x 22.7137")
+    field(THVL, "3")
+    field(FRST, "8 x 22.7137")
+    field(FRVL, "4")
+    field(FVST, "4 x 22.7137")
+    field(FVVL, "5")
+    field(SXST, "2 x 22.7137")
+    field(SXVL, "6")
+    field(SVST, "1 x 22.7137")
+    field(SVVL, "7")
+    field(SCAN, "I/O Intr")
+}
+
+record(bo, "$(P)$(R)Hyb$(HYB)Pol-S") {
+    field(DESC, "Hybrid's #$(HYB) Polarity")
+    field(DTYP, "asynInt32")
+    field(VAL,  "0")
+    field(ZNAM, "positive")
+    field(ONAM, "negative")
+    field(OUT,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_POLARITY")
+}
+
+record(bi, "$(P)$(R)Hyb$(HYB)Pol-RB") {
+    field(DESC, "Hybrid's #$(HYB) Polarity")
+    field(DTYP, "asynInt32")
+    field(VAL,  "0")
+    field(ZNAM, "positive")
+    field(ONAM, "negative")
+    field(INP,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_POLARITY")
+    field(SCAN, "I/O Intr")
+    field(PINI, "YES")
+}
+
 record(stringin, "$(P)$(R)Hyb$(HYB)ID-R") {
     field(DESC, "Hybrid $(HYB) ID")
     field(DTYP, "asynOctetRead")
+    field(PINI, "YES")
     field(INP,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_ID")
     field(SCAN, "I/O Intr")
 }
@@ -15,12 +163,15 @@ record(stringin, "$(P)$(R)Hyb$(HYB)ID-R") {
 record(stringin, "$(P)$(R)Hyb$(HYB)GeoPos-R") {
     field(DESC, "Hybrid $(HYB) Geo Position")
     field(DTYP, "asynOctetRead")
+    field(PINI, "YES")
     field(INP,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_GEOPOS")
     field(SCAN, "I/O Intr")
 }
 
 record(mbbi, "$(P)$(R)Hyb$(HYB)LinkStatus-R") {
     field(DESC, "Hybrid $(HYB) Link Status")
+    field(PINI, "YES")
+    field(DTYP, "asynInt32")
     field(ZRST, "not connected")
     field(ZRVL, "0")
     field(ONST, "start alignment")
@@ -34,6 +185,5 @@ record(mbbi, "$(P)$(R)Hyb$(HYB)LinkStatus-R") {
     field(FVST, "acq")
     field(FVVL, "5")
     field(SCAN, "I/O Intr")
-    field(DTYP, "asynInt32")
     field(INP,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_LINK_STATUS")
 }
diff --git a/vmmTblApp/Db/vmm_tbl.template b/vmmTblApp/Db/vmm_tbl.template
index 26af164409de408eac247592aefa274c0e410f28..350c05d9139991f65b7b715cd9d11b15598cf731 100644
--- a/vmmTblApp/Db/vmm_tbl.template
+++ b/vmmTblApp/Db/vmm_tbl.template
@@ -56,3 +56,11 @@ record(bo, "$(P)$(R)Acquire-S") {
     field(DTYP, "asynInt32")
     field(OUT,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))VMM_FEN_ACQUIRE")
 }
+
+record(ai, "$(P)$(R)RegBankVersion-R"){
+    field(DESC,  "Register bank version")
+    field(PINI,  "YES")
+    field(DTYP,  "asynInt32")
+    field(INP,   "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))REG_BANK_VERSION")
+    field(SCAN,  "I/O Intr")
+}
\ No newline at end of file
diff --git a/vmmTblApp/src/Utils.cpp b/vmmTblApp/src/Utils.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4f21ae82b0bb1ae9419aba6e1828aa52bf2557fc
--- /dev/null
+++ b/vmmTblApp/src/Utils.cpp
@@ -0,0 +1,63 @@
+#include <bits/stdc++.h>
+
+#include "Utils.h"
+
+/**
+ * @brief Gets index of number in vector.
+ * @param vec Vector to find number in
+ * @param function number to find.
+ * @return -1 if number is not found. -2 if number is repeated. Index of element if number is found.
+ **/
+int VecUtils::getIndex(std::vector<int>& vec, int function){
+
+    int c = std::count(vec.begin(), vec.end(), function);
+    if (c == 0) return -1;
+    if (c > 1) return -2;
+
+    auto it = std::find(vec.begin(), vec.end(), function);
+
+    if (it != vec.end()) return std::distance(vec.begin(), it);
+
+    return -1;
+
+}
+
+/**
+ * @brief Gets two indexes of number in vector<vector<int>>.
+ * @param vec Vector to find number in
+ * @param function number to find.
+ * @param hyb_index reference to put the hybrid index in.
+ * @param vmm_index reference to put the vmm index in.
+ * @return -1 if number is not found. -2 if number is repeated. 0 if number is found.
+ **/
+int VecUtils::getIndex(std::vector<std::vector<int>>& vec, int function, int &hyb_index, int &vmm_index) {
+    hyb_index = -1;
+    vmm_index = -1;
+
+    int occurrences = 0;
+
+    for (size_t i = 0; i < vec.size(); ++i) {
+        auto& subvec = vec[i];
+        auto it = std::find(subvec.begin(), subvec.end(), function);
+
+        if (it != subvec.end()) {
+            ++occurrences;
+            if (occurrences > 1) {
+                hyb_index = -2;
+                vmm_index = -2;
+                return -2; // Duplicated
+            }
+
+            hyb_index = static_cast<int>(i);
+            vmm_index = static_cast<int>(std::distance(subvec.begin(), it));
+        }
+    }
+
+    if (occurrences == 0) {
+        hyb_index = -1;
+        vmm_index = -1;
+        return -1; // Not found
+    }
+
+    return 0; // Found exactly once
+}
\ No newline at end of file
diff --git a/vmmTblApp/src/Utils.h b/vmmTblApp/src/Utils.h
new file mode 100644
index 0000000000000000000000000000000000000000..f6880efe93f850e7ad8cb691c6fa541a9bb59554
--- /dev/null
+++ b/vmmTblApp/src/Utils.h
@@ -0,0 +1,10 @@
+// Generic utilities for the module
+
+#include <vector>
+
+namespace VecUtils{
+
+int getIndex(std::vector<int>&, int function);
+int getIndex(std::vector<std::vector<int>>&, int function, int &hyb_index, int &vmm_index);
+
+}
\ No newline at end of file
diff --git a/vmmTblApp/src/vmm_tbl.cpp b/vmmTblApp/src/vmm_tbl.cpp
index 4b5ce9c8fb5991d775b054b2b64e080aa8dfea42..b2c535efbd33681fd10a2c6490adf3cfee20853a 100644
--- a/vmmTblApp/src/vmm_tbl.cpp
+++ b/vmmTblApp/src/vmm_tbl.cpp
@@ -6,8 +6,7 @@ VMMTbl::VMMTbl(RMM* rmm, const char *FENPortName, int ring, int node, int hybrid
       asynInt8ArrayMask | asynInt32Mask | asynInt64Mask | asynDrvUserMask | asynFloat64Mask | asynOctetMask,          // Interfaces that we implement
       asynInt8ArrayMask | asynInt64Mask | asynInt32ArrayMask | asynFloat64Mask | asynInt32Mask | asynOctetMask,       // Interfaces that do callbacks
       ASYN_MULTIDEVICE | ASYN_CANBLOCK, 1, /* ASYN_CANBLOCK=1, ASYN_MULTIDEVICE=1, autoConnect=1 */
-      0, 0),
-      number_hybrids(hybrids)
+      0, 0)
 {
 
   pVmmAPI = FrontEndFactory::createAndRegister<VMMAPI>(
@@ -15,183 +14,346 @@ VMMTbl::VMMTbl(RMM* rmm, const char *FENPortName, int ring, int node, int hybrid
     ring,
     node,
     "VmmTbl",
-    vmm_tbl_register_map);
+    vmm_tbl_register_map,
+    hybrids);
 
   createEpicsParams();
-  setInitialEpicsParams();
   rmm->updateTopologyPvs(ring, node, "vmmTbl");
-  if (rmm->getRMMAPI()->checkRings() == rmmSuccess) {
-    for (int hyb = 0; hyb < number_hybrids; hyb++) {
-      pVmmAPI->enableHybrid(hyb, true);
-      setStringParam(vmmHybFwVersion_[hyb], pVmmAPI->readFwVersion(hyb).c_str());
-      setStringParam(vmmHybId_[hyb], pVmmAPI->readIDChip(hyb).c_str());
-      setStringParam(vmmHybGeoPos_[hyb], pVmmAPI->readGeoPos(hyb).c_str());
-      setIntegerParam(vmmHybLinkStatus_[hyb], std::stoi(pVmmAPI->checkLinkStatus(hyb)));
+
+}
+
+asynStatus VMMTbl::readInt32(asynUser *pasynUser, epicsInt32 *value) {
+  int function = pasynUser->reason;
+  asynStatus status = asynSuccess;
+  uint32_t val;
+  int tmp_val;
+  bool tmp_val_bool;
+  uint8_t tmp_val_uint8;
+  int param_index;
+
+  if (function < FIRST_VMM_PARAM) {
+    return asynPortDriver::readInt32(pasynUser, value);
+  }
+
+  if (function == vmmRegBankVersion) {
+    vmmStatus result = this->pVmmAPI->getRegBankVersion(val);
+    if (result != vmmSuccess) status = asynError;
+    *value = val;
+    param_index = 10000; /// \todo So endOfReadInt32 won't return asynError; Maybe improve mechanism?
+    goto endOfReadInt32;
+  }
+
+  //Search for parameter in all parameter vectors. If found, execute correct function for specific hybrid.
+  param_index = VecUtils::getIndex(vmmHybSkew_, function);
+  if (param_index >= 0) {
+    this->pVmmAPI->getSkew(param_index, tmp_val_uint8);
+    *value = tmp_val_uint8;
+    goto endOfReadInt32;
+  }
+
+  param_index = VecUtils::getIndex(vmmHybLinkStatus_, function);
+  if (param_index >= 0) {
+    this->pVmmAPI->checkLinkStatus(param_index, tmp_val);
+    *value = tmp_val;
+    goto endOfReadInt32;
+  }
+
+  param_index = VecUtils::getIndex(vmmHybWidth_, function);
+  if (param_index >= 0) {
+    this->pVmmAPI->getWidth(param_index, tmp_val_uint8);
+    *value = tmp_val_uint8;
+    goto endOfReadInt32;
+  }
+
+  param_index = VecUtils::getIndex(vmmHybPolarity_, function);
+  if (param_index >= 0) {
+    this->pVmmAPI->getHybPolarity(param_index, tmp_val_bool);
+    *value = tmp_val_bool;
+    goto endOfReadInt32;
+  }
+
+  endOfReadInt32:
+  if (param_index < 0) {
+    *value = 0;
+    return asynError;
+  }
+
+  setIntegerParam(function, *value);
+  callParamCallbacks();
+
+  return asynSuccess;
+
+}
+
+asynStatus VMMTbl::readOctet(asynUser *pasynUser, char *value,
+                                    size_t nChars, size_t *nActual,
+									int *eomReason)
+{
+
+	int status = asynSuccess;
+	int function = pasynUser->reason;
+  std::string read = "";
+  
+  /* If this parameter belongs to a base class call its method */
+  if (function < FIRST_VMM_PARAM) {
+      status = asynPortDriver::readOctet(pasynUser, value, nChars, nActual,
+          eomReason);
+      return (asynStatus)status;
+  }
+
+  //Search for parameter in all parameter vectors. If found, execute correct function for specific hybrid.
+  int param_index = VecUtils::getIndex(vmmHybFwVersion_, function);
+  if (param_index >= 0) {
+    this->pVmmAPI->readFwVersion(param_index, read);
+    goto endOfReadOctet;
   }
+
+  param_index = VecUtils::getIndex(vmmHybId_, function);
+  if (param_index >= 0) {
+    this->pVmmAPI->readIDChip(param_index, read);
+    goto endOfReadOctet;
+  }
+
+  param_index = VecUtils::getIndex(vmmHybGeoPos_, function);
+  if (param_index >= 0) {
+    this->pVmmAPI->readGeoPos(param_index, read);
+    goto endOfReadOctet;
   }
+
+  endOfReadOctet:
+  if (param_index < 0) {
+    value[0] = '\0';
+    *nActual = 1;
+    return asynError;
+  }
+  size_t copy_size = std::min(read.size(), nChars);
+  strncpy(value, read.c_str(), copy_size);
+  setStringParam(function, value);
+  value[copy_size] = '\0';
+  *nActual = copy_size;
+  *eomReason = ASYN_EOM_END;
+  callParamCallbacks();
+
+  return asynSuccess;
+  
 }
 
-void VMMTbl::setInitialEpicsParams() {
-  puts("set_initial_epics_params");
+asynStatus VMMTbl::createParamAndStoreInVector(std::string paramName, asynParamType typ, 
+                                         std::vector<int>* vectorToStore){
+
+  int paramIndex;
+  asynStatus status = createParam(paramName.c_str(), typ, &paramIndex);
+  if (status != asynSuccess) {
+    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
+          "%s:%s: Failed to create paramter %s.\n",
+          driverName, __FUNCTION__, paramName.c_str());
+    return asynError;
+  }
+  vectorToStore->push_back(paramIndex);
+  return asynSuccess;
+
 }
 
 asynStatus VMMTbl::createEpicsParams() {
-  createParam("SEL_ANALOG_MONITOR_VMM0", asynParamInt32, &vmmSelectMonitorVMM0_);
-  createParam("SEL_ANALOG_MONITOR_VMM1", asynParamInt32, &vmmSelectMonitorVMM1_);
-  createParam("READ_ADC_VMMS", asynParamInt32, &vmmProcessReadMonitorVMMs_);
-  createParam("ADC_VALUE_VMM0", asynParamFloat64, &vmmMonitorValueVMM0_);
-  createParam("ADC_VALUE_VMM1", asynParamFloat64, &vmmMonitorValueVMM1_);
-  createParam("VMM_FEN_ACQUIRE", asynParamInt32, &vmmAcquire_);
-
-  for (int hyb = 0; hyb < number_hybrids; hyb++) {
-    std::ostringstream param_name;
-    param_name << "HYB_" << hyb <<"_FW_VERSION";
-    createParam(param_name.str().c_str(), asynParamOctet, &vmmHybFwVersion_[hyb]);
-    param_name.str("");
-    param_name << "HYB_" << hyb <<"_ID";
-    createParam(param_name.str().c_str(), asynParamOctet, &vmmHybId_[hyb]);
-    param_name.str("");
-    param_name << "HYB_" << hyb <<"_GEOPOS";
-    createParam(param_name.str().c_str(), asynParamOctet, &vmmHybGeoPos_[hyb]);
-    param_name.str("");
-    param_name << "HYB_" << hyb <<"_LINK_STATUS";
-    createParam(param_name.str().c_str(), asynParamInt32, &vmmHybLinkStatus_[hyb]);
-    for (int vmm=0; vmm < VMMS_PER_HYBRID; vmm++)
-    {
-    param_name.str("");
-    param_name << "HYB_" << hyb <<"_" << vmm << "_ST";
-    createParam(param_name.str().c_str(), asynParamInt8Array, &vmmST_[hyb][vmm]);
-    param_name.str("");
-    param_name << "HYB_" << hyb <<"_" << vmm << "_SC";
-    createParam(param_name.str().c_str(), asynParamInt8Array, &vmmSC_[hyb][vmm]);
-    param_name.str("");
-    param_name << "HYB_" << hyb <<"_" << vmm << "_SL";
-    createParam(param_name.str().c_str(), asynParamInt8Array, &vmmSL_[hyb][vmm]);
-    param_name.str("");
-    param_name << "HYB_" << hyb <<"_" << vmm << "_STH";
-    createParam(param_name.str().c_str(), asynParamInt8Array, &vmmSTH_[hyb][vmm]);
-    param_name.str("");
-    param_name << "HYB_" << hyb <<"_" << vmm << "_SM";
-    createParam(param_name.str().c_str(), asynParamInt8Array, &vmmSM_[hyb][vmm]);
-    param_name.str("");
-    param_name << "HYB_" << hyb <<"_" << vmm << "_SMX";
-    createParam(param_name.str().c_str(), asynParamInt8Array, &vmmSMX_[hyb][vmm]);
+
+  createParam("REG_BANK_VERSION", asynParamInt32, &vmmRegBankVersion);
+
+  std::tuple<std::string, asynParamType, std::vector<int>*> 
+                              hyb_params_to_create[7] = {{"_FW_VERSION", asynParamOctet, &vmmHybFwVersion_},
+                                                    {"_ID", asynParamOctet, &vmmHybId_},
+                                                    {"_GEOPOS", asynParamOctet, &vmmHybGeoPos_},
+                                                    {"_LINK_STATUS", asynParamInt32, &vmmHybLinkStatus_},
+                                                    {"_SKEW", asynParamInt32, &vmmHybSkew_},
+                                                    {"_WIDTH", asynParamInt32, &vmmHybWidth_},
+                                                    {"_POLARITY", asynParamInt32, &vmmHybPolarity_}};
+
+  std::ostringstream param_name;
+
+  for (int hyb = 0; hyb < this->pVmmAPI->getNumHybrids(true); hyb++) {
+
+    for (const auto& hyb_param : hyb_params_to_create){
+      const std::string& key = std::get<0>(hyb_param);
+      asynParamType typ = std::get<1>(hyb_param);
+      std::vector<int>* vec = std::get<2>(hyb_param);
+      createParamAndStoreInVector("HYB_" + std::to_string(hyb) + key, typ, vec);
     }
+
+    std::vector<int> SC, SL, ST, STH, SM, SMX;
+    
+    for (int vmm=0; vmm < VMMS_PER_HYBRID; vmm++) {
+
+
+      param_name.str("");
+      param_name << "HYB_" << hyb <<"_" << vmm << "_SC";
+      createParamAndStoreInVector(param_name.str(), asynParamInt8Array, &SC);
+
+      param_name.str("");
+      param_name << "HYB_" << hyb <<"_" << vmm << "_SL";
+      createParamAndStoreInVector(param_name.str(), asynParamInt8Array, &SL);
+
+      param_name.str("");
+      param_name << "HYB_" << hyb <<"_" << vmm << "_ST";
+      createParamAndStoreInVector(param_name.str(), asynParamInt8Array, &ST);
+
+      param_name.str("");
+      param_name << "HYB_" << hyb <<"_" << vmm << "_STH";
+      createParamAndStoreInVector(param_name.str(), asynParamInt8Array, &STH);
+
+      param_name.str("");
+      param_name << "HYB_" << hyb <<"_" << vmm << "_SM";
+      createParamAndStoreInVector(param_name.str(), asynParamInt8Array, &SM);
+
+      param_name.str("");
+      param_name << "HYB_" << hyb <<"_" << vmm << "_SMX";
+      createParamAndStoreInVector(param_name.str(), asynParamInt8Array, &SMX);
+
+    }
+
+    this->vmmSC_.push_back(SC);
+    this->vmmSL_.push_back(SL);
+    this->vmmST_.push_back(ST);
+    this->vmmSTH_.push_back(STH);
+    this->vmmSM_.push_back(SM);
+    this->vmmSMX_.push_back(SMX);
+
   }
 
   return asynSuccess;
 }
 
 asynStatus VMMTbl::writeInt32(asynUser *pasynUser, epicsInt32 value) {
+
   asynStatus status = asynSuccess;
+  vmmStatus vmm_stat;
   int function = pasynUser->reason;
+  int param_index = -1;
 
-  if ((value) && (function == vmmProcessReadMonitorVMMs_)) {
-    int adc_sensor = 0;
-    for (int vmm = 0; vmm <= 1; vmm++) {
-      getIntegerParam(vmmSelectMonitorVMM0_ + vmm, &adc_sensor);
-      std::cout << "adc_sensor" << adc_sensor << std::endl;
-      pVmmAPI->getHybrid(0).getVMM(vmm).setRegister("sm5_sm0", adc_sensor + 64);
-      pVmmAPI->configVMM(0, vmm);
-      int adc_read = pVmmAPI->readADC(0, vmm);
-
-      std::cout << "adc_read" << adc_read << std::endl;
-
-      if (adc_sensor == 3) {
-        double temperature = (725 - adc_read) / 1.85;
-        setDoubleParam(vmmMonitorValueVMM0_ + vmm, temperature);
-      }
-      else {
-        setDoubleParam(vmmMonitorValueVMM0_ + vmm, adc_read);
-      }
-    }
+  // if (function == vmmAcquire_) {
+  
+  //   if (value) pVmmAPI->acquire(true);
+  //   else pVmmAPI->acquire(false);
+
+  //   for (int hyb = 0; hyb < number_hybrids; hyb++)
+  //     setIntegerParam(vmmHybLinkStatus_[hyb], std::stoi(pVmmAPI->checkLinkStatus(hyb)));
+  // }
+
+  if (function < FIRST_VMM_PARAM) {
+    return asynPortDriver::writeInt32(pasynUser, value);
   }
 
-  else if (function == vmmAcquire_) {
-  
-    if (value) pVmmAPI->acquire(true);
-    else pVmmAPI->acquire(false);
+  //Search for parameter in all parameter vectors. If found, execute correct function for specific hybrid.
+  param_index = VecUtils::getIndex(vmmHybSkew_, function);
+  if (param_index >= 0) {
+    vmm_stat = this->pVmmAPI->setSkew(param_index, value);
+    if (vmm_stat != vmmSuccess) status = asynError;
+    goto endOfWriteInt32;
+  }
+
+  param_index = VecUtils::getIndex(vmmHybWidth_, function);
+  if (param_index >= 0) {
+    vmm_stat = this->pVmmAPI->setWidth(param_index, value);
+    if (vmm_stat != vmmSuccess) status = asynError;
+    goto endOfWriteInt32;
+  }
+
+  param_index = VecUtils::getIndex(vmmHybPolarity_, function);
+  if (param_index >= 0) {
+    vmm_stat = this->pVmmAPI->setHybPolarity(param_index, value);
+    if (vmm_stat != vmmSuccess) status = asynError;
+    goto endOfWriteInt32;
+  }
 
-    for (int hyb = 0; hyb < number_hybrids; hyb++)
-      setIntegerParam(vmmHybLinkStatus_[hyb], std::stoi(pVmmAPI->checkLinkStatus(hyb)));
+  endOfWriteInt32:
+  if (param_index < 0) {
+    status = asynError;
   }
 
+  setIntegerParam(function, value);
+  callParamCallbacks();
+
   return status;
+
 }
 
-asynStatus VMMTbl::writeInt8Array(asynUser *pasynUser, epicsInt8 *value, size_t nElements)
-{
+asynStatus VMMTbl::readInt8Array(asynUser *pasynUser, epicsInt8 *value, size_t nElements, size_t *nIn){
 
-  int function, addr;
-  int ncopy = CHANNELS_PER_VMM;
-  const char *paramName;
-  const char *functionName = "writeInt8Array";
-  int status = asynSuccess;
-  std::vector<epicsInt8> int8Array;
-  Reg pair;
+  int function, hyb_index, vmm_index, found_param = -10, status = 0;
+  bool data;
+  const char* paramName;
 
-  status |= parseAsynUser(pasynUser, &function, &addr, &paramName);
+  function = pasynUser->reason;
   getParamName(function, &paramName);
-  status |= findRegister(function, &pair);
-  if (status) {
-    asynPrint(pasynUser, ASYN_TRACE_ERROR,
-              "%s:%s: function=%d, name=%s, value=%d. Cannot find which Hybrid-VMM pair is function related to.\n",
-              driverName, functionName, function, paramName, *value);
-    return (asynStatus) status;
+
+  if (function < FIRST_VMM_PARAM) return asynPortDriver::readInt8Array(pasynUser, value, nElements, nIn);
+
+  found_param = VecUtils::getIndex(vmmST_, function, hyb_index, vmm_index);
+  if (found_param == 0) {
+    for (size_t i = 0; i < nElements; i++) {
+      status |= (int)this->pVmmAPI->getST(hyb_index, vmm_index, i, data);
+      value[i] = data;
+    }
+    goto endOfReadInt8Array;
+  }
+
+  endOfReadInt8Array:
+  if (found_param != 0) {
+    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
+      "%s:%s: Failed to find paramter %s, index %d.\n",
+      driverName, __FUNCTION__, paramName, function);
+    *nIn = 0;
+    return asynError;
   }
 
-  asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
-            "%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());
+  *nIn = nElements;
 
-  for (epicsInt8 i = 0; i < ncopy; ++i) {
-    int8Array.push_back(static_cast<int>(value[i]) >= 1 ? 1 : 0);
-    pVmmAPI->getHybrid(pair.hyb).getVMM(pair.vmm).setRegister(pair.rg.c_str(),
-                                                  static_cast<int>(value[i]),
-                                                  i);
+  if (status) {
+    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
+      "%s:%s: Failed to get paramter %s, index %d.\n",
+      driverName, __FUNCTION__, paramName, function);
+    return asynError;
   }
 
-  status |= doCallbacksInt8Array(int8Array.data(), int8Array.size(), function, 0);
-  return (asynStatus) status;
+  return asynSuccess;
 
 }
 
-asynStatus VMMTbl::findRegister(int function, Reg *reg_){
+asynStatus VMMTbl::writeInt8Array(asynUser *pasynUser, epicsInt8 *value, size_t nElements)
+{
 
-  int (*array)[VMMS_PER_HYBRID];
-  std::map<std::string, int(*)[VMMS_PER_HYBRID]>::iterator it;
+  int function, hyb_index, vmm_index, status = 0, found_param = -10;
+  const char* paramName;
 
-  it = this->registers.begin();
+  function = pasynUser->reason;
+  getParamName(function, &paramName);
 
-  while ( it != this->registers.end() ){
-    std::string reg_name = it->first;
-    array = registers[reg_name];
+  if (function < FIRST_VMM_PARAM) return asynPortDriver::writeInt8Array(pasynUser, value, nElements);
 
-    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;
-        }
-      }
+  found_param = VecUtils::getIndex(vmmST_, function, hyb_index, vmm_index);
+  if (found_param == 0) {
+    for (size_t i = 0; i < nElements; i++) {
+      status |= (int)this->pVmmAPI->setST(hyb_index, vmm_index, i, (bool)value[i]);
     }
-
-    it++;
+    goto endOfWriteInt8Array;
   }
 
-  return asynError;
+  endOfWriteInt8Array:
+  status |= (int)doCallbacksInt8Array(value, nElements, function, 0); // Comparing different statuses, yes.
+  if (found_param != 0) {
+    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
+      "%s:%s: Failed to find paramter %s, index %d.\n",
+      driverName, __FUNCTION__, paramName, function);
+    return asynError;
+  }
 
-}
+  if (status) {
+    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
+      "%s:%s: Failed to set paramter %s.\n",
+      driverName, __FUNCTION__, paramName);
+    return asynError;
+  }
 
-asynStatus VMMTbl::writeFloat64(asynUser *pasynUser, epicsFloat64 value) {
-  asynStatus status = asynSuccess;
-  int addr = 0;
-  getAddress(pasynUser, &addr);
+  return asynSuccess;
 
-  return status;
 }
 
 extern "C" {
diff --git a/vmmTblApp/src/vmm_tbl.h b/vmmTblApp/src/vmm_tbl.h
index 597fd5cdab3fc6288e64433d84546b2f54d2b118..83a573fdc17594afa901cee7740f7ba394b768c8 100644
--- a/vmmTblApp/src/vmm_tbl.h
+++ b/vmmTblApp/src/vmm_tbl.h
@@ -2,49 +2,65 @@
 
 #include "rmm.h"
 #include "VMMAPI.h"
+#include "Utils.h"
 
-/* Struct to hold Hyb, VMM pair values */
-struct Reg {
-  int hyb = -1;
-  int vmm = -1;
-  std::string rg = "\0";
+/* Struct to hold Hyb, VMM and epics parameter values */
+struct ParamValues {
+  int param = -1;
+  std::string value;
 };
 
 /** Class definition for the VMMTbl class */
 class VMMTbl : public asynPortDriver {
 public:
   VMMTbl(RMM* rmm, const char *FENPortName, int ring, int node, int hybrids);
+
+  /* Epics parameter management */
   asynStatus createEpicsParams();
 	virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
-  virtual asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value);
+  // virtual asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value);
   virtual asynStatus writeInt8Array(asynUser *pasynUser, epicsInt8 *value, size_t nElements);
-  void setInitialEpicsParams();
-  asynStatus findRegister(int function, Reg *reg_);
+  virtual asynStatus readInt8Array(asynUser *pasynUser, epicsInt8 *value, size_t nElements, size_t *nIn);
+  virtual asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value);
+  virtual asynStatus readOctet(asynUser *pasynUser, char *value, size_t maxChars, size_t *nActual, int *eomReason);
+  asynStatus createParamAndStoreInVector(std::string paramName, asynParamType typ, 
+                                         std::vector<int>* vectorToStore);
 
 protected:
+  int vmmRegBankVersion;
+#define FIRST_VMM_PARAM vmmRegBankVersion
   int vmmSelectMonitorVMM0_;
   int vmmSelectMonitorVMM1_;
   int vmmProcessReadMonitorVMMs_;
   int vmmMonitorValueVMM0_;
   int vmmMonitorValueVMM1_;
   int vmmAcquire_;
-  int vmmHybFwVersion_[HYBRIDS_PER_FEN];
-  int vmmHybId_[HYBRIDS_PER_FEN];
-  int vmmHybGeoPos_[HYBRIDS_PER_FEN];
-  int vmmHybLinkStatus_[HYBRIDS_PER_FEN];
-  //Registers channels per hybrid, per VMM
-  int vmmST_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID];
-  int vmmSL_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID];
-  int vmmSC_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID];
-  int vmmSTH_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID];
-  int vmmSM_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID];
-  int vmmSMX_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID];
-  std::map<std::string, int(*)[VMMS_PER_HYBRID]> registers{{"st", vmmST_}, {"sc", vmmSC_},
-                                                           {"sl", vmmSL_}, {"sth", vmmSTH_},
-                                                           {"sm", vmmSM_}, {"smx", vmmSMX_}};
+  std::vector<int> vmmHybFwVersion_;
+  std::vector<int> vmmHybId_;
+  std::vector<int> vmmHybGeoPos_;
+  std::vector<int> vmmHybLinkStatus_;
+  std::vector<int> vmmHybSkew_;
+  std::vector<int> vmmHybWidth_;
+  std::vector<int> vmmHybPolarity_;
+  std::vector<std::vector<int>> vmmSC_;
+  std::vector<std::vector<int>> vmmSL_;
+  std::vector<std::vector<int>> vmmST_;
+  std::vector<std::vector<int>> vmmSTH_;
+  std::vector<std::vector<int>> vmmSM_;
+  std::vector<std::vector<int>> vmmSD_;
+  std::vector<std::vector<int>> vmmSMX_;
+  // //Registers channels per hybrid, per VMM
+  // int vmmST_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID];
+  // int vmmSL_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID];
+  // int vmmSC_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID];
+  // int vmmSTH_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID];
+  // int vmmSM_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID];
+  // int vmmSMX_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID];
+  // std::map<std::string, int(*)[VMMS_PER_HYBRID]> registers{{"st", vmmST_}, {"sc", vmmSC_},
+  //                                                          {"sl", vmmSL_}, {"sth", vmmSTH_},
+  //                                                          {"sm", vmmSM_}, {"smx", vmmSMX_}};
 
 private:
   static constexpr const char *driverName = "VMMTbl";
   std::shared_ptr<VMMAPI> pVmmAPI;
-  int number_hybrids;
 };