Skip to content
Snippets Groups Projects
vmm_tbl.cpp 26.2 KiB
Newer Older
Douglas Araujo's avatar
Douglas Araujo committed
#include "vmm_tbl.h"

/** Constructor for the VMMTbl class */
Marco Filho's avatar
Marco Filho committed
VMMTbl::VMMTbl(RMM *rmm, const char *FENPortName, int ring, int node, int hybrids)
    : asynPortDriver(FENPortName, 0,
                     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) {
  pVmmAPI =
      FrontEndFactory::createAndRegister<VMMAPI>(rmm->getRMMAPI(), ring, node, "VmmTbl", vmm_tbl_register_map, hybrids);
  rmm->updateTopologyPvs(ring, node, "vmmTbl");

  setStringParam(IOCMessage, "Finished starting IOC.");
  callParamCallbacks();
Marco Filho's avatar
Marco Filho committed
}

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;
Marco Filho's avatar
Marco Filho committed
  vmmStatus result = vmmSuccess;
  int param_index = 0, hyb_index, vmm_index;
  const char *paramName;

  getParamName(function, &paramName);
Marco Filho's avatar
Marco Filho committed

  if (function < FIRST_VMM_PARAM) {
    return asynPortDriver::readInt32(pasynUser, value);
  }

Marco Filho's avatar
Marco Filho committed
  if (function == vmmAcquire_) {
    status = getIntegerParam(vmmAcquire_, value);
    goto endOfReadInt32;
  }

Marco Filho's avatar
Marco Filho committed
  if (function == vmmRegBankVersion) {
Marco Filho's avatar
Marco Filho committed
    result = this->pVmmAPI->getRegBankVersion(val);
Marco Filho's avatar
Marco Filho committed
    *value = val;
    goto endOfReadInt32;
  }

  if (function == vmmNumHybrids) {
    *value = this->pVmmAPI->getNumHybrids(true);
    goto endOfReadInt32;
  }

  if (function == vmmIsAcquiring_) {
Marco Filho's avatar
Marco Filho committed
    result = this->pVmmAPI->isAcquiring(tmp_val_bool);
    *value = tmp_val_bool;
Marco Filho's avatar
Marco Filho committed
    goto endOfReadInt32;
  }

Marco Filho's avatar
Marco Filho committed
  // Search for parameter in all parameter vectors. If found, execute correct function for specific hybrid.
Marco Filho's avatar
Marco Filho committed
  param_index = VecUtils::getIndex(vmmHybSkew_, function);
  if (param_index >= 0) {
Marco Filho's avatar
Marco Filho committed
    result = this->pVmmAPI->getSkew(param_index, tmp_val_uint8);
Marco Filho's avatar
Marco Filho committed
    *value = tmp_val_uint8;
    goto endOfReadInt32;
  }

  param_index = VecUtils::getIndex(vmmHybEnable_, function);
  if (param_index >= 0) {
    result = this->pVmmAPI->isHybridEnabled(param_index, tmp_val_bool);
    *value = tmp_val_bool;
    goto endOfReadInt32;
  }

Marco Filho's avatar
Marco Filho committed
  param_index = VecUtils::getIndex(vmmHybLinkStatus_, function);
  if (param_index >= 0) {
Marco Filho's avatar
Marco Filho committed
    result = this->pVmmAPI->checkLinkStatus(param_index, tmp_val);
Marco Filho's avatar
Marco Filho committed
    *value = tmp_val;
    goto endOfReadInt32;
  }

  param_index = VecUtils::getIndex(vmmHybWidth_, function);
  if (param_index >= 0) {
Marco Filho's avatar
Marco Filho committed
    result = this->pVmmAPI->getWidth(param_index, tmp_val_uint8);
Marco Filho's avatar
Marco Filho committed
    *value = tmp_val_uint8;
    goto endOfReadInt32;
  }

  param_index = VecUtils::getIndex(vmmHybPolarity_, function);
  if (param_index >= 0) {
Marco Filho's avatar
Marco Filho committed
    result = this->pVmmAPI->getHybPolarity(param_index, tmp_val_bool);
Marco Filho's avatar
Marco Filho committed
    *value = tmp_val_bool;
    goto endOfReadInt32;
  }

Marco Filho's avatar
Marco Filho committed
  param_index = VecUtils::getIndex(vmmADCIDX_, function, hyb_index, vmm_index);
  if (param_index == 0) {
Marco Filho's avatar
Marco Filho committed
    result = this->pVmmAPI->getADCIdx(hyb_index, vmm_index, tmp_val);
    *value = tmp_val;
    goto endOfReadInt32;
  }

Marco Filho's avatar
Marco Filho committed
  param_index = VecUtils::getIndex(vmmADCVAL_, function, hyb_index, vmm_index);
Marco Filho's avatar
Marco Filho committed
  if (param_index == 0) {
Marco Filho's avatar
Marco Filho committed
    result = this->pVmmAPI->readADC(hyb_index, vmm_index, tmp_val);
Marco Filho's avatar
Marco Filho committed
    *value = tmp_val;
    goto endOfReadInt32;
  }

Marco Filho's avatar
Marco Filho committed
  param_index = VecUtils::getIndex(vmmBdg_, function, hyb_index, vmm_index);
  if (param_index == 0) {
    GenericParameter param_value;
    result = this->pVmmAPI->getBandgap(hyb_index, vmm_index, param_value);
    *value = param_value.value_int;
    goto endOfReadInt32;
  }

  param_index = VecUtils::getIndex(vmmThr_, function, hyb_index, vmm_index);
  if (param_index == 0) {
    GenericParameter param_value;
    result = this->pVmmAPI->getThresholdADC(hyb_index, vmm_index, param_value);
    *value = param_value.value_int;
    goto endOfReadInt32;
  }

  param_index = VecUtils::getIndex(vmmPls_, function, hyb_index, vmm_index);
  if (param_index == 0) {
    GenericParameter param_value;
    result = this->pVmmAPI->getPulserADC(hyb_index, vmm_index, param_value);
    *value = param_value.value_int;
    goto endOfReadInt32;
  }

Marco Filho's avatar
Marco Filho committed
endOfReadInt32:
Marco Filho's avatar
Marco Filho committed
  if (param_index < 0) {
Marco Filho's avatar
Marco Filho committed
    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Failed to find parameter %s, index: %d.\n", driverName,
              __FUNCTION__, paramName, function);
    std::string message = "Failed to find parameter: " + std::to_string(*paramName);
    setStringParam(IOCMessage, message.c_str());
Marco Filho's avatar
Marco Filho committed
    *value = 0;
    return asynError;
  }
Marco Filho's avatar
Marco Filho committed
  if (result != vmmSuccess) {
Marco Filho's avatar
Marco Filho committed
    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Failed to adequately read parameter: %d.\n", driverName,
              __FUNCTION__, function);
    std::string message = "Failed to read parameter: " + std::to_string(*paramName);
    setStringParam(IOCMessage, message.c_str());
Marco Filho's avatar
Marco Filho committed
    status = asynError;
  }
Marco Filho's avatar
Marco Filho committed

  setIntegerParam(function, *value);
  callParamCallbacks();

Marco Filho's avatar
Marco Filho committed
  return status;
Marco Filho's avatar
Marco Filho committed
}

asynStatus VMMTbl::readFloat64(asynUser *pasynUser, epicsFloat64 *value) {
  int function = pasynUser->reason;
  asynStatus status = asynSuccess;
  GenericParameter val;
  vmmStatus result = vmmSuccess;
  int param_index = 0, hyb_index, vmm_index;
  const char *paramName;

  getParamName(function, &paramName);

  if (function < FIRST_VMM_PARAM) {
    return asynPortDriver::readFloat64(pasynUser, value);
  }

  // Search for parameter in adequate parameter vectors. If found, execute correct function for specific hybrid.
  param_index = VecUtils::getIndex(vmmTemp_, function, hyb_index, vmm_index);
  if (param_index >= 0) {
    result = this->pVmmAPI->getTemperature(hyb_index, vmm_index, val);
    *value = (epicsFloat64)val.value_float;
    goto endOfReadFloat64;
  }

endOfReadFloat64:
  if (param_index < 0) {
    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Failed to find parameter %d.\n", driverName, __FUNCTION__,
              function);
    std::string message = "Failed to find parameter: " + std::to_string(*paramName);
    setStringParam(IOCMessage, message.c_str());
    *value = 0;
    return asynError;
  }
  if (result != vmmSuccess) {
    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Failed to adequately read parameter: %d.\n", driverName,
              __FUNCTION__, function);
    std::string message = "Failed to read parameter: " + std::to_string(*paramName);
    setStringParam(IOCMessage, message.c_str());
    status = asynError;
  }

  setDoubleParam(function, *value);
  callParamCallbacks();

  return status;
}

Marco Filho's avatar
Marco Filho committed
asynStatus VMMTbl::readOctet(asynUser *pasynUser, char *value, size_t nChars, size_t *nActual, int *eomReason) {
  asynStatus status = asynSuccess;
Marco Filho's avatar
Marco Filho committed
  vmmStatus result;
Marco Filho's avatar
Marco Filho committed
  int function = pasynUser->reason;
  int hyb_index, vmm_index;
Marco Filho's avatar
Marco Filho committed
  std::string read = "";
  const char *paramName;

  getParamName(function, &paramName);
Marco Filho's avatar
Marco Filho committed
  /* If this parameter belongs to a base class call its method */
  if (function < FIRST_VMM_PARAM) {
Marco Filho's avatar
Marco Filho committed
    return asynPortDriver::readOctet(pasynUser, value, nChars, nActual, eomReason);
Marco Filho's avatar
Marco Filho committed
  }

Marco Filho's avatar
Marco Filho committed
  // Search for parameter in all parameter vectors. If found, execute correct function for specific hybrid.
Marco Filho's avatar
Marco Filho committed
  int param_index = VecUtils::getIndex(vmmHybFwVersion_, function);
  if (param_index >= 0) {
Marco Filho's avatar
Marco Filho committed
    result = this->pVmmAPI->readFwVersion(param_index, read);
Marco Filho's avatar
Marco Filho committed
    goto endOfReadOctet;
Marco Filho's avatar
Marco Filho committed

  param_index = VecUtils::getIndex(vmmHybId_, function);
  if (param_index >= 0) {
Marco Filho's avatar
Marco Filho committed
    result = this->pVmmAPI->readIDChip(param_index, read);
Marco Filho's avatar
Marco Filho committed
    goto endOfReadOctet;
  }

  param_index = VecUtils::getIndex(vmmHybGeoPos_, function);
  if (param_index >= 0) {
Marco Filho's avatar
Marco Filho committed
    result = this->pVmmAPI->readGeoPos(param_index, read);
Marco Filho's avatar
Marco Filho committed
    goto endOfReadOctet;
Marco Filho's avatar
Marco Filho committed

  param_index = VecUtils::getIndex(vmmTempTmstp_, function, hyb_index, vmm_index);
  if (param_index >= 0) {
    GenericParameter val;
    result = this->pVmmAPI->getTemperature(hyb_index, vmm_index, val);
Marco Filho's avatar
Marco Filho committed
    read = TimeUtils::timeToStr(val.timestamp);
    goto endOfReadOctet;
  }

  param_index = VecUtils::getIndex(vmmBdgTmstp_, function, hyb_index, vmm_index);
  if (param_index >= 0) {
    GenericParameter val;
    result = this->pVmmAPI->getBandgap(hyb_index, vmm_index, val);
    read = TimeUtils::timeToStr(val.timestamp);
    goto endOfReadOctet;
  }
Marco Filho's avatar
Marco Filho committed
  param_index = VecUtils::getIndex(vmmThrTmstp_, function, hyb_index, vmm_index);
  if (param_index >= 0) {
    GenericParameter val;
    result = this->pVmmAPI->getThresholdADC(hyb_index, vmm_index, val);
    read = TimeUtils::timeToStr(val.timestamp);
    goto endOfReadOctet;
  }

  param_index = VecUtils::getIndex(vmmPlsTmstp_, function, hyb_index, vmm_index);
  if (param_index >= 0) {
    GenericParameter val;
    result = this->pVmmAPI->getPulserADC(hyb_index, vmm_index, val);
    read = TimeUtils::timeToStr(val.timestamp);
Marco Filho's avatar
Marco Filho committed
endOfReadOctet:
Marco Filho's avatar
Marco Filho committed
  if (param_index < 0) {
Marco Filho's avatar
Marco Filho committed
    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Failed to find parameter %s, index: %d.\n", driverName,
              __FUNCTION__, paramName, function);
    std::string message = "Failed to find parameter: " + std::to_string(*paramName);
    setStringParam(IOCMessage, message.c_str());
Marco Filho's avatar
Marco Filho committed
    value[0] = '\0';
    *nActual = 1;
    return asynError;
  }
Marco Filho's avatar
Marco Filho committed
  if (result != vmmSuccess) {
Marco Filho's avatar
Marco Filho committed
    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Failed to adequately read parameter: %s, index: %d.\n",
              driverName, __FUNCTION__, paramName, function);
    std::string message = "Failed to read parameter: " + std::to_string(*paramName);
    setStringParam(IOCMessage, message.c_str());
Marco Filho's avatar
Marco Filho committed
    status = asynError;
  }
Marco Filho's avatar
Marco Filho committed
  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();

Marco Filho's avatar
Marco Filho committed
  return status;
asynStatus VMMTbl::createParamAndStoreInVector(std::string paramName, asynParamType typ,
Marco Filho's avatar
Marco Filho committed
                                               std::vector<int> *vectorToStore) {
Marco Filho's avatar
Marco Filho committed
  int paramIndex;
  asynStatus status = createParam(paramName.c_str(), typ, &paramIndex);
  if (status != asynSuccess) {
    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Failed to create parameter %s.\n", driverName, __FUNCTION__,
Marco Filho's avatar
Marco Filho committed
              paramName.c_str());
Marco Filho's avatar
Marco Filho committed
    return asynError;
  }
  vectorToStore->push_back(paramIndex);
  return asynSuccess;
Marco Filho's avatar
Marco Filho committed
  createParam("REG_BANK_VERSION", asynParamInt32, &vmmRegBankVersion);
  createParam("VMM_FEN_ACQUIRE", asynParamInt32, &vmmAcquire_);
  createParam("VMM_FEN_ACQUIRING", asynParamInt32, &vmmIsAcquiring_);
  createParam("NUM_HYBRIDS", asynParamInt32, &vmmNumHybrids);
  createParam("IOC_MESSAGE", asynParamOctet, &IOCMessage);
Marco Filho's avatar
Marco Filho committed

  std::tuple<std::string, asynParamType, std::vector<int> *> hyb_params_to_create[8] = {
Marco Filho's avatar
Marco Filho committed
      {"_FW_VERSION", asynParamOctet, &vmmHybFwVersion_},
      {"_ID", asynParamOctet, &vmmHybId_},
      {"_GEOPOS", asynParamOctet, &vmmHybGeoPos_},
      {"_LINK_STATUS", asynParamInt32, &vmmHybLinkStatus_},
      {"_SKEW", asynParamInt32, &vmmHybSkew_},
      {"_WIDTH", asynParamInt32, &vmmHybWidth_},
      {"_ENABLE", asynParamInt32, &vmmHybEnable_},
Marco Filho's avatar
Marco Filho committed
      {"_POLARITY", asynParamInt32, &vmmHybPolarity_}};
Marco Filho's avatar
Marco Filho committed

  std::ostringstream param_name;

  for (int hyb = 0; hyb < this->pVmmAPI->getNumHybrids(); hyb++) {
Marco Filho's avatar
Marco Filho committed
    for (const auto &hyb_param : hyb_params_to_create) {
      const std::string &key = std::get<0>(hyb_param);
Marco Filho's avatar
Marco Filho committed
      asynParamType typ = std::get<1>(hyb_param);
Marco Filho's avatar
Marco Filho committed
      std::vector<int> *vec = std::get<2>(hyb_param);
Marco Filho's avatar
Marco Filho committed
      createParamAndStoreInVector("HYB_" + std::to_string(hyb) + key, typ, vec);
Marco Filho's avatar
Marco Filho committed

Marco Filho's avatar
Marco Filho committed
    std::vector<int> SC, SL, ST, STH, SM, SD, SMX, ADCIDX, ADCVAL;
    std::vector<int> TEMP, TEMPTMSTP, BDG, BDGTMPSTP, THR, THRTMPSTP, PLS, PLSTMPSTP;
Marco Filho's avatar
Marco Filho committed
    for (int vmm = 0; vmm < VMMS_PER_HYBRID; vmm++) {
Marco Filho's avatar
Marco Filho committed
      param_name.str("");
Marco Filho's avatar
Marco Filho committed
      param_name << "HYB_" << hyb << "_" << vmm << "_SC";
Marco Filho's avatar
Marco Filho committed
      createParamAndStoreInVector(param_name.str(), asynParamInt8Array, &SC);

      param_name.str("");
Marco Filho's avatar
Marco Filho committed
      param_name << "HYB_" << hyb << "_" << vmm << "_SL";
Marco Filho's avatar
Marco Filho committed
      createParamAndStoreInVector(param_name.str(), asynParamInt8Array, &SL);

      param_name.str("");
Marco Filho's avatar
Marco Filho committed
      param_name << "HYB_" << hyb << "_" << vmm << "_ST";
Marco Filho's avatar
Marco Filho committed
      createParamAndStoreInVector(param_name.str(), asynParamInt8Array, &ST);

      param_name.str("");
Marco Filho's avatar
Marco Filho committed
      param_name << "HYB_" << hyb << "_" << vmm << "_STH";
Marco Filho's avatar
Marco Filho committed
      createParamAndStoreInVector(param_name.str(), asynParamInt8Array, &STH);

      param_name.str("");
Marco Filho's avatar
Marco Filho committed
      param_name << "HYB_" << hyb << "_" << vmm << "_SM";
Marco Filho's avatar
Marco Filho committed
      createParamAndStoreInVector(param_name.str(), asynParamInt8Array, &SM);

Marco Filho's avatar
Marco Filho committed
      param_name.str("");
Marco Filho's avatar
Marco Filho committed
      param_name << "HYB_" << hyb << "_" << vmm << "_SD";
Marco Filho's avatar
Marco Filho committed
      createParamAndStoreInVector(param_name.str(), asynParamInt8Array, &SD);

Marco Filho's avatar
Marco Filho committed
      param_name.str("");
Marco Filho's avatar
Marco Filho committed
      param_name << "HYB_" << hyb << "_" << vmm << "_SMX";
Marco Filho's avatar
Marco Filho committed
      createParamAndStoreInVector(param_name.str(), asynParamInt8Array, &SMX);

      param_name.str("");
Marco Filho's avatar
Marco Filho committed
      param_name << "HYB_" << hyb << "_" << vmm << "_ANALOGMON";
Marco Filho's avatar
Marco Filho committed
      createParamAndStoreInVector(param_name.str(), asynParamInt32, &ADCIDX);
Marco Filho's avatar
Marco Filho committed
      param_name.str("");
Marco Filho's avatar
Marco Filho committed
      param_name << "HYB_" << hyb << "_" << vmm << "_ADCVAL";
Marco Filho's avatar
Marco Filho committed
      createParamAndStoreInVector(param_name.str(), asynParamInt32, &ADCVAL);

      param_name.str("");
      param_name << "HYB_" << hyb << "_" << vmm << "_TEMP";
      createParamAndStoreInVector(param_name.str(), asynParamFloat64, &TEMP);

      param_name.str("");
      param_name << "HYB_" << hyb << "_" << vmm << "_TMP_TMSTP";
      createParamAndStoreInVector(param_name.str(), asynParamOctet, &TEMPTMSTP);
Marco Filho's avatar
Marco Filho committed

      param_name.str("");
      param_name << "HYB_" << hyb << "_" << vmm << "_BDG";
      createParamAndStoreInVector(param_name.str(), asynParamInt32, &BDG);

      param_name.str("");
      param_name << "HYB_" << hyb << "_" << vmm << "_BDG_TMSTP";
      createParamAndStoreInVector(param_name.str(), asynParamOctet, &BDGTMPSTP);

      param_name.str("");
      param_name << "HYB_" << hyb << "_" << vmm << "_THR";
      createParamAndStoreInVector(param_name.str(), asynParamInt32, &THR);

      param_name.str("");
      param_name << "HYB_" << hyb << "_" << vmm << "_THR_TMSTP";
      createParamAndStoreInVector(param_name.str(), asynParamOctet, &THRTMPSTP);

      param_name.str("");
      param_name << "HYB_" << hyb << "_" << vmm << "_PLS";
      createParamAndStoreInVector(param_name.str(), asynParamInt32, &PLS);

      param_name.str("");
      param_name << "HYB_" << hyb << "_" << vmm << "_PLS_TMSTP";
      createParamAndStoreInVector(param_name.str(), asynParamOctet, &PLSTMPSTP);
Marco Filho's avatar
Marco Filho committed
    }

    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);
Marco Filho's avatar
Marco Filho committed
    this->vmmSD_.push_back(SD);
Marco Filho's avatar
Marco Filho committed
    this->vmmSMX_.push_back(SMX);
Marco Filho's avatar
Marco Filho committed
    this->vmmADCIDX_.push_back(ADCIDX);
    this->vmmADCVAL_.push_back(ADCVAL);
    this->vmmTemp_.push_back(TEMP);
    this->vmmTempTmstp_.push_back(TEMPTMSTP);
Marco Filho's avatar
Marco Filho committed
    this->vmmBdg_.push_back(BDG);
    this->vmmBdgTmstp_.push_back(BDGTMPSTP);
    this->vmmThr_.push_back(THR);
    this->vmmThrTmstp_.push_back(THRTMPSTP);
    this->vmmPls_.push_back(PLS);
    this->vmmPlsTmstp_.push_back(PLSTMPSTP);
Douglas Araujo's avatar
Douglas Araujo committed
  return asynSuccess;
}

asynStatus VMMTbl::writeInt32(asynUser *pasynUser, epicsInt32 value) {
  asynStatus status = asynSuccess;
Marco Filho's avatar
Marco Filho committed
  vmmStatus vmm_stat = vmmSuccess;
  bool is_acquiring;
Douglas Araujo's avatar
Douglas Araujo committed
  int function = pasynUser->reason;
  int param_index = 0, hyb_index, vmm_index;
  const char *paramName;

  getParamName(function, &paramName);
Marco Filho's avatar
Marco Filho committed

  if (function < FIRST_VMM_PARAM) {
    return asynPortDriver::writeInt32(pasynUser, value);
  if (function == vmmAcquire_) {
Marco Filho's avatar
Marco Filho committed
    setStringParam(IOCMessage, std::string("Set acquire to " + std::to_string(value)).c_str());
    vmm_stat = this->pVmmAPI->isAcquiring(is_acquiring);
    if (is_acquiring == (bool)value) {
      setStringParam(IOCMessage, "Error: Set to acquire/stop but already acquiring/stopped.");
      status = asynError;
    } else {
      this->pVmmAPI->acquire((bool)value);
    }

    goto endOfWriteInt32;
  }

Marco Filho's avatar
Marco Filho committed
  // Search for parameter in all parameter vectors. If found, execute correct function for specific hybrid.
Marco Filho's avatar
Marco Filho committed
  param_index = VecUtils::getIndex(vmmHybSkew_, function);
  if (param_index >= 0) {
Marco Filho's avatar
Marco Filho committed
    setStringParam(
        IOCMessage,
        std::string("Set skew from hybrid " + std::to_string(param_index) + " to " + std::to_string(value)).c_str());
Marco Filho's avatar
Marco Filho committed
    vmm_stat = this->pVmmAPI->setSkew(param_index, value);
    goto endOfWriteInt32;
  }

  param_index = VecUtils::getIndex(vmmHybEnable_, function);
  if (param_index >= 0) {
Marco Filho's avatar
Marco Filho committed
    setStringParam(IOCMessage, std::string("Setting enable/disable for hybrid " + std::to_string(param_index) + " to " +
                                           std::to_string(value))
                                   .c_str());
    vmm_stat = this->pVmmAPI->enableHybrid(param_index, (bool)value);
    goto endOfWriteInt32;
  }

Marco Filho's avatar
Marco Filho committed
  param_index = VecUtils::getIndex(vmmHybWidth_, function);
  if (param_index >= 0) {
Marco Filho's avatar
Marco Filho committed
    setStringParam(
        IOCMessage,
        std::string("Set width from hybrid " + std::to_string(param_index) + " to " + std::to_string(value)).c_str());
Marco Filho's avatar
Marco Filho committed
    vmm_stat = this->pVmmAPI->setWidth(param_index, value);
    goto endOfWriteInt32;
  }

  param_index = VecUtils::getIndex(vmmHybPolarity_, function);
  if (param_index >= 0) {
Marco Filho's avatar
Marco Filho committed
    setStringParam(IOCMessage, std::string("Set polarity from hybrid " + std::to_string(param_index) + " to " +
                                           std::to_string(value))
                                   .c_str());
Marco Filho's avatar
Marco Filho committed
    vmm_stat = this->pVmmAPI->setHybPolarity(param_index, value);
    goto endOfWriteInt32;
  }
Marco Filho's avatar
Marco Filho committed
  param_index = VecUtils::getIndex(vmmADCIDX_, function, hyb_index, vmm_index);
  if (param_index == 0) {
Marco Filho's avatar
Marco Filho committed
    setStringParam(IOCMessage, std::string("Set ADC index of hybrid " + std::to_string(hyb_index) + ", vmm " +
                                           std::to_string(vmm_index) + " to " + std::to_string(value))
                                   .c_str());
Marco Filho's avatar
Marco Filho committed
    vmm_stat = this->pVmmAPI->setADCIdx(hyb_index, vmm_index, value);
Marco Filho's avatar
Marco Filho committed
endOfWriteInt32:
Marco Filho's avatar
Marco Filho committed
  if (param_index < 0) {
Marco Filho's avatar
Marco Filho committed
    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Failed to find parameter %s, index: %d.\n", driverName,
              __FUNCTION__, paramName, function);
    std::string message = "Failed to find parameter: " + std::to_string(*paramName);
    setStringParam(IOCMessage, message.c_str());
    status = asynError;
  }
  if (vmm_stat != vmmSuccess) {
Marco Filho's avatar
Marco Filho committed
    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Failed to write to parameter %s, index: %d.\n", driverName,
              __FUNCTION__, paramName, function);
    std::string message = "Failed to write to parameter: " + std::to_string(*paramName);
    setStringParam(IOCMessage, message.c_str());
Marco Filho's avatar
Marco Filho committed
    status = asynError;
Marco Filho's avatar
Marco Filho committed
  setIntegerParam(function, value);
  callParamCallbacks();

Douglas Araujo's avatar
Douglas Araujo committed
  return status;
}

Marco Filho's avatar
Marco Filho committed
asynStatus VMMTbl::readInt8Array(asynUser *pasynUser, epicsInt8 *value, size_t nElements, size_t *nIn) {
Marco Filho's avatar
Marco Filho committed
  int function, hyb_index, vmm_index, found_param = -10, status = 0;
Marco Filho's avatar
Marco Filho committed
  uint8_t data_int;
Marco Filho's avatar
Marco Filho committed
  bool data;
Marco Filho's avatar
Marco Filho committed
  const char *paramName;
Marco Filho's avatar
Marco Filho committed
  function = pasynUser->reason;
  getParamName(function, &paramName);
Marco Filho's avatar
Marco Filho committed

  if (function < FIRST_VMM_PARAM) return asynPortDriver::readInt8Array(pasynUser, value, nElements, nIn);

  found_param = VecUtils::getIndex(vmmSC_, function, hyb_index, vmm_index);
  if (found_param == 0) {
    for (size_t i = 0; i < nElements; i++) {
      status |= (int)this->pVmmAPI->getSC(hyb_index, vmm_index, i, data);
      value[i] = data;
    }
    goto endOfReadInt8Array;
  }

  found_param = VecUtils::getIndex(vmmSL_, function, hyb_index, vmm_index);
  if (found_param == 0) {
    for (size_t i = 0; i < nElements; i++) {
      status |= (int)this->pVmmAPI->getSL(hyb_index, vmm_index, i, data);
      value[i] = data;
    }
    goto endOfReadInt8Array;
  }

Marco Filho's avatar
Marco Filho committed
  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;
  }

  found_param = VecUtils::getIndex(vmmSTH_, function, hyb_index, vmm_index);
  if (found_param == 0) {
    for (size_t i = 0; i < nElements; i++) {
      status |= (int)this->pVmmAPI->getSTH(hyb_index, vmm_index, i, data);
      value[i] = data;
    }
    goto endOfReadInt8Array;
  }

  found_param = VecUtils::getIndex(vmmSM_, function, hyb_index, vmm_index);
  if (found_param == 0) {
    for (size_t i = 0; i < nElements; i++) {
      status |= (int)this->pVmmAPI->getSM(hyb_index, vmm_index, i, data);
      value[i] = data;
    }
    goto endOfReadInt8Array;
  }

Marco Filho's avatar
Marco Filho committed
  found_param = VecUtils::getIndex(vmmSD_, function, hyb_index, vmm_index);
  if (found_param == 0) {
    for (size_t i = 0; i < nElements; i++) {
      status |= (int)this->pVmmAPI->getSD(hyb_index, vmm_index, i, data_int);
      value[i] = data_int;
    }
    goto endOfReadInt8Array;
  }

  found_param = VecUtils::getIndex(vmmSMX_, function, hyb_index, vmm_index);
  if (found_param == 0) {
    for (size_t i = 0; i < nElements; i++) {
      status |= (int)this->pVmmAPI->getSMX(hyb_index, vmm_index, i, data);
      value[i] = data;
    }
    goto endOfReadInt8Array;
  }

Marco Filho's avatar
Marco Filho committed
endOfReadInt8Array:
Marco Filho's avatar
Marco Filho committed
  if (found_param != 0) {
    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Failed to find parameter %s, index %d.\n", driverName,
Marco Filho's avatar
Marco Filho committed
              __FUNCTION__, paramName, function);
    std::string message = "Failed to find parameter: " + std::to_string(*paramName);
    setStringParam(IOCMessage, message.c_str());
Marco Filho's avatar
Marco Filho committed
    *nIn = 0;
    return asynError;
Marco Filho's avatar
Marco Filho committed
  }
Marco Filho's avatar
Marco Filho committed
  *nIn = nElements;
Marco Filho's avatar
Marco Filho committed
  status |= (int)doCallbacksInt8Array(value, nElements, function, 0);
Marco Filho's avatar
Marco Filho committed
  if (status) {
Marco Filho's avatar
Marco Filho committed
    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Failed to get paramter %s, index %d.\n", driverName,
              __FUNCTION__, paramName, function);
    std::string message = "Failed to read parameter: " + std::to_string(*paramName);
    setStringParam(IOCMessage, message.c_str());
Marco Filho's avatar
Marco Filho committed
    return asynError;
Marco Filho's avatar
Marco Filho committed
  return asynSuccess;
Marco Filho's avatar
Marco Filho committed
asynStatus VMMTbl::writeInt8Array(asynUser *pasynUser, epicsInt8 *value, size_t nElements) {
Marco Filho's avatar
Marco Filho committed
  int function, hyb_index, vmm_index, status = 0, found_param = -10;
Marco Filho's avatar
Marco Filho committed
  const char *paramName;
Marco Filho's avatar
Marco Filho committed
  function = pasynUser->reason;
  getParamName(function, &paramName);
Marco Filho's avatar
Marco Filho committed
  if (function < FIRST_VMM_PARAM) return asynPortDriver::writeInt8Array(pasynUser, value, nElements);
  found_param = VecUtils::getIndex(vmmSC_, function, hyb_index, vmm_index);
  if (found_param == 0) {
    for (size_t i = 0; i < nElements; i++) {
      status |= (int)this->pVmmAPI->setSC(hyb_index, vmm_index, i, (bool)value[i]);
    }
    goto endOfWriteInt8Array;
  }

  found_param = VecUtils::getIndex(vmmSL_, function, hyb_index, vmm_index);
  if (found_param == 0) {
    for (size_t i = 0; i < nElements; i++) {
      status |= (int)this->pVmmAPI->setSL(hyb_index, vmm_index, i, (bool)value[i]);
    }
    goto endOfWriteInt8Array;
  }

Marco Filho's avatar
Marco Filho committed
  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]);
Marco Filho's avatar
Marco Filho committed
    goto endOfWriteInt8Array;
  found_param = VecUtils::getIndex(vmmSTH_, function, hyb_index, vmm_index);
  if (found_param == 0) {
    for (size_t i = 0; i < nElements; i++) {
      status |= (int)this->pVmmAPI->setSTH(hyb_index, vmm_index, i, (bool)value[i]);
    }
    goto endOfWriteInt8Array;
  }

  found_param = VecUtils::getIndex(vmmSM_, function, hyb_index, vmm_index);
  if (found_param == 0) {
    for (size_t i = 0; i < nElements; i++) {
      status |= (int)this->pVmmAPI->setSM(hyb_index, vmm_index, i, (bool)value[i]);
    }
    goto endOfWriteInt8Array;
  }

  found_param = VecUtils::getIndex(vmmSMX_, function, hyb_index, vmm_index);
  if (found_param == 0) {
    for (size_t i = 0; i < nElements; i++) {
      status |= (int)this->pVmmAPI->setSMX(hyb_index, vmm_index, i, (bool)value[i]);
    }
    goto endOfWriteInt8Array;
  }

Marco Filho's avatar
Marco Filho committed
  found_param = VecUtils::getIndex(vmmSD_, function, hyb_index, vmm_index);
  if (found_param == 0) {
    for (size_t i = 0; i < nElements; i++) {
      status |= (int)this->pVmmAPI->setSD(hyb_index, vmm_index, i, value[i]);
    }
    goto endOfWriteInt8Array;
  }

Marco Filho's avatar
Marco Filho committed
endOfWriteInt8Array:
  status |= (int)doCallbacksInt8Array(value, nElements, function, 0);  // Comparing different statuses, yes.
Marco Filho's avatar
Marco Filho committed
  if (found_param != 0) {
    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Failed to find parameter %s, index %d.\n", driverName,
Marco Filho's avatar
Marco Filho committed
              __FUNCTION__, paramName, function);
    std::string message = "Failed to find parameter: " + std::to_string(*paramName);
    setStringParam(IOCMessage, message.c_str());
Marco Filho's avatar
Marco Filho committed
    return asynError;
  }
Marco Filho's avatar
Marco Filho committed
  if (status) {
Marco Filho's avatar
Marco Filho committed
    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Failed to set paramter %s.\n", driverName, __FUNCTION__,
              paramName);
    std::string message = "Failed to write to parameter: " + std::to_string(*paramName);
    setStringParam(IOCMessage, message.c_str());
Marco Filho's avatar
Marco Filho committed
    return asynError;
  }
Marco Filho's avatar
Marco Filho committed
  return asynSuccess;
Douglas Araujo's avatar
Douglas Araujo committed
}

extern "C" {
Marco Filho's avatar
Marco Filho committed
static void VMMTblConfig(const char *RMMPortName, const char *FENPortName, int ring, int hybrids) {
  int node = 0;  // VMM use always only the Node 0
  RMM *pRMM;
  pRMM = (RMM *)findAsynPortDriver(RMMPortName);
  if (pRMM != nullptr) {
    new VMMTbl(pRMM, FENPortName, ring, node, hybrids);
  } else {
    std::cerr << "Error: Failed to find RMM for port " << RMMPortName << std::endl;
Douglas Araujo's avatar
Douglas Araujo committed
  }
Marco Filho's avatar
Marco Filho committed
}
Douglas Araujo's avatar
Douglas Araujo committed

Marco Filho's avatar
Marco Filho committed
static const iocshArg configArg0 = {"RMM Port name", iocshArgString};
static const iocshArg configArg1 = {"Front End Port Name", iocshArgString};
static const iocshArg configArg2 = {"Ring", iocshArgInt};
static const iocshArg configArg3 = {"Hybrids", iocshArgInt};
Douglas Araujo's avatar
Douglas Araujo committed

Marco Filho's avatar
Marco Filho committed
static const iocshArg *const configArgs[] = {&configArg0, &configArg1, &configArg2, &configArg3};
Douglas Araujo's avatar
Douglas Araujo committed

Marco Filho's avatar
Marco Filho committed
static const iocshFuncDef configFuncDef = {"VMMTblConfig", 4, configArgs};
Douglas Araujo's avatar
Douglas Araujo committed

Marco Filho's avatar
Marco Filho committed
static void configCallFunc(const iocshArgBuf *args) {
  VMMTblConfig(args[0].sval, args[1].sval, args[2].ival, args[3].ival);
}
Douglas Araujo's avatar
Douglas Araujo committed

Marco Filho's avatar
Marco Filho committed
static void VMMTblRegister(void) {
  iocshRegister(&configFuncDef, configCallFunc);
}
Douglas Araujo's avatar
Douglas Araujo committed

Marco Filho's avatar
Marco Filho committed
epicsExportRegistrar(VMMTblRegister);
}  // end extern "C"