asynStatus NDPluginCircularBuff::calculateTrigger(NDArray *pArray, int *trig)
{
    NDAttribute *trigger;
    char triggerString[256];
    double triggerValue;
    double calcResult;
    int status;
    int preTrigger, postTrigger, currentImage, triggered;
    static const char *functionName="calculateTrigger";
    
    *trig = 0;
    
    getIntegerParam(NDCircBuffPreTrigger,   &preTrigger);
    getIntegerParam(NDCircBuffPostTrigger,  &postTrigger);
    getIntegerParam(NDCircBuffCurrentImage, &currentImage);
    getIntegerParam(NDCircBuffTriggered,    &triggered);   

    triggerCalcArgs_[0] = epicsNAN;
    triggerCalcArgs_[1] = epicsNAN;
    triggerCalcArgs_[2] = preTrigger;
    triggerCalcArgs_[3] = postTrigger;
    triggerCalcArgs_[4] = currentImage;
    triggerCalcArgs_[5] = triggered;

    getStringParam(NDCircBuffTriggerA, sizeof(triggerString), triggerString);
    trigger = pArray->pAttributeList->find(triggerString);
    if (trigger != NULL) {
        status = trigger->getValue(NDAttrFloat64, &triggerValue);
        if (status == asynSuccess) {
            triggerCalcArgs_[0] = triggerValue;
        }
    }
    getStringParam(NDCircBuffTriggerB, sizeof(triggerString), triggerString);
    trigger = pArray->pAttributeList->find(triggerString);
    if (trigger != NULL) {
        status = trigger->getValue(NDAttrFloat64, &triggerValue);
        if (status == asynSuccess) {
            triggerCalcArgs_[1] = triggerValue;
        }
    }
    
    setDoubleParam(NDCircBuffTriggerAVal, triggerCalcArgs_[0]);
    setDoubleParam(NDCircBuffTriggerBVal, triggerCalcArgs_[1]);
    status = calcPerform(triggerCalcArgs_, &calcResult, triggerCalcPostfix_);
    if (status) {
        asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
            "%s::%s error evaluating expression=%s\n",
            driverName, functionName, calcErrorStr(status));
        return asynError;
    }
    
    if (!isnan(calcResult) && !isinf(calcResult) && (calcResult != 0)) *trig = 1;
    setDoubleParam(NDCircBuffTriggerCalcVal, calcResult);

    return asynSuccess;
}
/** Called when asyn clients call pasynOctet->write().
  * This function performs actions for some parameters, including AttributesFile.
  * For all parameters it sets the value in the parameter library and calls any registered callbacks..
  * \param[in] pasynUser pasynUser structure that encodes the reason and address.
  * \param[in] value Address of the string to write.
  * \param[in] nChars Number of characters to write.
  * \param[out] nActual Number of characters actually written. */
asynStatus NDPluginCircularBuff::writeOctet(asynUser *pasynUser, const char *value, size_t nChars, size_t *nActual)
{
  int addr=0;
  int function = pasynUser->reason;
  asynStatus status = asynSuccess;
  short postfixError;
  const char *functionName = "writeOctet";

  status = getAddress(pasynUser, &addr); if (status != asynSuccess) return(status);
  // Set the parameter in the parameter library.
  status = (asynStatus)setStringParam(addr, function, (char *)value);
  if (status != asynSuccess) return(status);

  if (function == NDCircBuffTriggerCalc){
    if (nChars > sizeof(triggerCalcInfix_)) nChars = sizeof(triggerCalcInfix_);
    // If the input string is empty then use a value of "0", otherwise there is an error
    if ((value == 0) || (strlen(value) == 0)) {
      strcpy(triggerCalcInfix_, DEFAULT_TRIGGER_CALC);
      setStringParam(NDCircBuffTriggerCalc, DEFAULT_TRIGGER_CALC);
    } else {
      strncpy(triggerCalcInfix_, value, nChars);
    }
    status = (asynStatus)postfix(triggerCalcInfix_, triggerCalcPostfix_, &postfixError);
    if (status) {
      asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
      "%s::%s error processing infix expression=%s, error=%s\n",
      driverName, functionName, triggerCalcInfix_, calcErrorStr(postfixError));
    }
  } 
  
  else if (function < FIRST_NDPLUGIN_CIRC_BUFF_PARAM) {
      /* If this parameter belongs to a base class call its method */
      status = NDPluginDriver::writeOctet(pasynUser, value, nChars, nActual);
  }

  // Do callbacks so higher layers see any changes
  callParamCallbacks(addr, addr);

  if (status){
    epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
                  "%s:%s: status=%d, function=%d, value=%s",
                  driverName, functionName, status, function, value);
  } else {
    asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
              "%s:%s: function=%d, value=%s\n",
              driverName, functionName, function, value);
  }
  *nActual = nChars;
  return status;
}
Exemple #3
0
static long special(DBADDR *paddr, int after)
{
    calcoutRecord *prec = (calcoutRecord *)paddr->precord;
    rpvtStruct  *prpvt = prec->rpvt;
    DBADDR      dbaddr;
    DBADDR      *pAddr = &dbaddr;
    short       error_number;
    int         fieldIndex = dbGetFieldIndex(paddr);
    int         lnkIndex;
    DBLINK      *plink;
    double      *pvalue;
    epicsEnum16 *plinkValid;

    if (!after) return 0;
    switch(fieldIndex) {
      case(calcoutRecordCALC):
        prec->clcv = postfix(prec->calc, prec->rpcl, &error_number);
        if (prec->clcv){
            recGblRecordError(S_db_badField, (void *)prec,
                      "calcout: special(): Illegal CALC field");
            errlogPrintf("%s.CALC: %s in expression \"%s\"\n",
                         prec->name, calcErrorStr(error_number), prec->calc);
        }
        db_post_events(prec, &prec->clcv, DBE_VALUE);
        return 0;

      case(calcoutRecordOCAL):
        prec->oclv = postfix(prec->ocal, prec->orpc, &error_number);
        if (prec->dopt == calcoutDOPT_Use_OVAL && prec->oclv){
            recGblRecordError(S_db_badField, (void *)prec,
                    "calcout: special(): Illegal OCAL field");
            errlogPrintf("%s.OCAL: %s in expression \"%s\"\n",
                         prec->name, calcErrorStr(error_number), prec->ocal);
        }
        db_post_events(prec, &prec->oclv, DBE_VALUE);
        return 0;
      case(calcoutRecordINPA):
      case(calcoutRecordINPB):
      case(calcoutRecordINPC):
      case(calcoutRecordINPD):
      case(calcoutRecordINPE):
      case(calcoutRecordINPF):
      case(calcoutRecordINPG):
      case(calcoutRecordINPH):
      case(calcoutRecordINPI):
      case(calcoutRecordINPJ):
      case(calcoutRecordINPK):
      case(calcoutRecordINPL):
      case(calcoutRecordOUT):
        lnkIndex = fieldIndex - calcoutRecordINPA;
        plink   = &prec->inpa + lnkIndex;
        pvalue  = &prec->a    + lnkIndex;
        plinkValid = &prec->inav + lnkIndex;
        if (plink->type == CONSTANT) {
            if (fieldIndex != calcoutRecordOUT) {
                recGblInitConstantLink(plink, DBF_DOUBLE, pvalue);
                db_post_events(prec, pvalue, DBE_VALUE);
            }
            *plinkValid = calcoutINAV_CON;
        } else if (!dbNameToAddr(plink->value.pv_link.pvname, pAddr)) {
            /* if the PV resides on this ioc */
            *plinkValid = calcoutINAV_LOC;
        } else {
            /* pv is not on this ioc. Callback later for connection stat */
            *plinkValid = calcoutINAV_EXT_NC;
            /* DO_CALLBACK, if not already scheduled */
            if (!prpvt->cbScheduled) {
                callbackRequestDelayed(&prpvt->checkLinkCb, .5);
                prpvt->cbScheduled = 1;
                prpvt->caLinkStat = CA_LINKS_NOT_OK;
            }
        }
        db_post_events(prec, plinkValid, DBE_VALUE);
        return 0;
      case(calcoutRecordOEVT):
        prec->epvt = eventNameToHandle(prec->oevt);
        return 0;
      default:
        recGblDbaddrError(S_db_badChoice, paddr, "calc: special");
        return(S_db_badChoice);
    }
}
Exemple #4
0
static long init_record(calcoutRecord *prec, int pass)
{
    DBLINK *plink;
    int i;
    double *pvalue;
    epicsEnum16 *plinkValid;
    short error_number;
    calcoutDSET *pcalcoutDSET;

    DBADDR     dbaddr;
    DBADDR     *pAddr = &dbaddr;
    rpvtStruct *prpvt;

    if (pass == 0) {
        prec->rpvt = (rpvtStruct *) callocMustSucceed(1, sizeof(rpvtStruct), "calcoutRecord");
        return 0;
    }
    if (!(pcalcoutDSET = (calcoutDSET *)prec->dset)) {
        recGblRecordError(S_dev_noDSET, (void *)prec, "calcout:init_record");
        return S_dev_noDSET;
    }
    /* must have write defined */
    if ((pcalcoutDSET->number < 5) || (pcalcoutDSET->write ==NULL)) {
        recGblRecordError(S_dev_missingSup, (void *)prec, "calcout:init_record");
        return S_dev_missingSup;
    }
    prpvt = prec->rpvt;
    plink = &prec->inpa;
    pvalue = &prec->a;
    plinkValid = &prec->inav;
    for (i = 0; i <= CALCPERFORM_NARGS; i++, plink++, pvalue++, plinkValid++) {
        if (plink->type == CONSTANT) {
            /* Don't InitConstantLink the .OUT link */
            if (i < CALCPERFORM_NARGS) {
                recGblInitConstantLink(plink, DBF_DOUBLE, pvalue);
            }
            *plinkValid = calcoutINAV_CON;
        } else if (!dbNameToAddr(plink->value.pv_link.pvname, pAddr)) {
            /* PV resides on this ioc */
            *plinkValid = calcoutINAV_LOC;
        } else {
            /* pv is not on this ioc. Callback later for connection stat */
            *plinkValid = calcoutINAV_EXT_NC;
             prpvt->caLinkStat = CA_LINKS_NOT_OK;
        }
    }

    prec->clcv = postfix(prec->calc, prec->rpcl, &error_number);
    if (prec->clcv){
        recGblRecordError(S_db_badField, (void *)prec,
                          "calcout: init_record: Illegal CALC field");
        errlogPrintf("%s.CALC: %s in expression \"%s\"\n",
                     prec->name, calcErrorStr(error_number), prec->calc);
    }

    prec->oclv = postfix(prec->ocal, prec->orpc, &error_number);
    if (prec->dopt == calcoutDOPT_Use_OVAL && prec->oclv){
        recGblRecordError(S_db_badField, (void *)prec,
                          "calcout: init_record: Illegal OCAL field");
        errlogPrintf("%s.OCAL: %s in expression \"%s\"\n",
                     prec->name, calcErrorStr(error_number), prec->ocal);
    }

    prpvt = prec->rpvt;
    callbackSetCallback(checkLinksCallback, &prpvt->checkLinkCb);
    callbackSetPriority(0, &prpvt->checkLinkCb);
    callbackSetUser(prec, &prpvt->checkLinkCb);
    prpvt->cbScheduled = 0;

    prec->epvt = eventNameToHandle(prec->oevt);
    
    if (pcalcoutDSET->init_record) pcalcoutDSET->init_record(prec);
    prec->pval = prec->val;
    prec->mlst = prec->val;
    prec->alst = prec->val;
    prec->lalm = prec->val;
    prec->povl = prec->oval;
    return 0;
}