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, ¤tImage); 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; }
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); } }
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; }