Exemple #1
0
static long processAo(aoRecord *pr)
{
    devInt32Pvt *pPvt = (devInt32Pvt *)pr->dpvt;
    asynStatus status;
    double     value;
    
    if (getCallbackValue(pPvt)) {
        /* We got a callback from the driver */
        if (pPvt->result.status == asynSuccess) {
            pr->rval = pPvt->result.value;
            pr->udf = 0;
            value = (double)pr->rval + (double)pr->roff;
            if(pr->aslo!=0.0) value *= pr->aslo;
            value += pr->aoff;
            if (pr->linr == menuConvertNO_CONVERSION){
                ; /*do nothing*/
            } else if ((pr->linr == menuConvertLINEAR) ||
                       (pr->linr == menuConvertSLOPE)) {
                value = value*pr->eslo + pr->eoff;
            } else {
                if(cvtRawToEngBpt(&value,pr->linr,pr->init,
                        (void *)&pr->pbrk,&pr->lbrk)!=0) {
                    asynPrint(pPvt->pasynUser, ASYN_TRACE_ERROR,
                        "%s devAsynInt32 cvtRawToEngBpt failed\n",
                        pr->name);
                    (void)recGblSetSevr(pr, WRITE_ALARM, INVALID_ALARM);
                    return -1;
                }
            }
            pr->val = value;
            pr->udf = isnan(value);
        }
    } else if(pr->pact == 0) {
        pPvt->result.value = pr->rval;
        if(pPvt->canBlock) pr->pact = 1;
        status = pasynManager->queueRequest(pPvt->pasynUser, 0, 0);
        if((status==asynSuccess) && pPvt->canBlock) return 0;
        if(pPvt->canBlock) pr->pact = 0;
        reportQueueRequestStatus(pPvt, status);
    }
    if(pPvt->result.status == asynSuccess) {
        return 0;
    }
    else {
        pasynEpicsUtils->asynStatusToEpicsAlarm(pPvt->result.status, WRITE_ALARM, &pPvt->alarmStat,
                                                INVALID_ALARM, &pPvt->alarmSevr);
        (void)recGblSetSevr(pr, pPvt->alarmStat, pPvt->alarmSevr);
        pPvt->result.status = asynSuccess;
        return -1;
    }
}
static long processAo(aoRecord *pr)
{
    devInt32Pvt *pPvt = (devInt32Pvt *)pr->dpvt;
    asynStatus status;
    double     value;
    
    getCallbackValue(pPvt);
    if(pPvt->gotValue) {
        /* This code is for I/O Intr scanned output records, which are not tested yet. */
        pr->rval = pPvt->value;
        pr->udf = 0;
        value = (double)pr->rval + (double)pr->roff;
        if(pr->aslo!=0.0) value *= pr->aslo;
        value += pr->aoff;
        if (pr->linr == menuConvertNO_CONVERSION){
            ; /*do nothing*/
        } else if ((pr->linr == menuConvertLINEAR) ||
                  (pr->linr == menuConvertSLOPE)) {
            value = value*pr->eslo + pr->eoff;
        }else{
            if(cvtRawToEngBpt(&value,pr->linr,pr->init,
                    (void *)&pr->pbrk,&pr->lbrk)!=0) {
                asynPrint(pPvt->pasynUser, ASYN_TRACE_ERROR,
                    "%s devAsynInt32 cvtRawToEngBpt failed\n",
                    pr->name);
                recGblSetSevr(pr, READ_ALARM, INVALID_ALARM);
                goto done;
            }
        }
        pr->val = value;
        pr->udf = isnan(value);
    } else if(pr->pact == 0) {
        pPvt->value = pr->rval;
        if(pPvt->canBlock) pr->pact = 1;
        status = pasynManager->queueRequest(pPvt->pasynUser, 0, 0);
        if((status==asynSuccess) && pPvt->canBlock) return 0;
        if(pPvt->canBlock) pr->pact = 0;
        if(status != asynSuccess) {
            asynPrint(pPvt->pasynUser, ASYN_TRACE_ERROR,
                "%s devAsynInt32 queueRequest %s\n",
                pr->name,pPvt->pasynUser->errorMessage);
            recGblSetSevr(pr, WRITE_ALARM, INVALID_ALARM);
        }
    }
done:
    pPvt->gotValue = 0;
    return 0;
}
Exemple #3
0
static void convert(aiRecord *prec)
{
	double val;


	val = (double)prec->rval + (double)prec->roff;
	/* adjust slope and offset */
	if(prec->aslo!=0.0) val*=prec->aslo;
	val+=prec->aoff;

	/* convert raw to engineering units and signal units */
	switch (prec->linr) {
	case menuConvertNO_CONVERSION:
		break; /* do nothing*/
	
	case menuConvertLINEAR:
	case menuConvertSLOPE:
		val = (val * prec->eslo) + prec->eoff;
		break;
	
	default: /* must use breakpoint table */
                if (cvtRawToEngBpt(&val,prec->linr,prec->init,(void *)&prec->pbrk,&prec->lbrk)!=0) {
                      recGblSetSevr(prec,SOFT_ALARM,MAJOR_ALARM);
                }
	}

	/* apply smoothing algorithm */
	if (prec->smoo != 0.0){
	    if (prec->init) prec->val = val;	/* initial condition */
	    prec->val = val * (1.00 - prec->smoo) + (prec->val * prec->smoo);
	}else{
	    prec->val = val;
	}
	prec->udf = isnan(prec->val);
	return;
}
Exemple #4
0
/* Callback from driver for every received tag, for ao record:
 * Check if
 *
 * 1) pact set -> this is the "finshed the write" callback
 * 2) pact not set -> this is the "new value" callback
 *    Tag value is either different from current record value
 *    or there is no current record value:
 * 2a) disconnected; process record to set WRITE/INVALID
 * 2b) PLC's value != record's idea of the current value
 * 2c) record is UDF, so this is the first time we get a value
 *     from the PLC after a reboot
 * Causing process if necessary to update the record.
 * That process()/scanOnce() call should NOT cause the record to write
 * to the PLC because the xxx_write method will notice that
 * the PLC and record value agree.
 * It will, however, trigger CA monitors.
 *
 * Problem: Alarms are handled before "write_xx" is called.
 * So we have to set udf in here,
 * then process() can recognize udf and finally it will
 * call write_xx.
 */
static void check_ao_callback(void *arg)
{
    aoRecord      *rec = (aoRecord *) arg;
    struct rset   *rset= (struct rset *)(rec->rset);
    DevicePrivate *pvt = (DevicePrivate *)rec->dpvt;
    double        dbl;
    CN_DINT       dint;
    eip_bool      process = false;

    /* We are about the check and even set val, & rval -> lock */
    dbScanLock((dbCommon *)rec);
    if (rec->pact)
    {
        if (rec->tpro)
            printf("EIP check_ao_callback('%s'), pact=%d\n",
                   rec->name, rec->pact);
        (*rset->process) ((dbCommon *)rec);
        dbScanUnlock((dbCommon *)rec);
        return;
    }
    /* Check if record's (R)VAL is current */
    if (!check_data((dbCommon *)rec))
    {
        if (rec->tpro)
            printf("EIP check_ao_callback('%s'), no data\n", rec->name);
        (*rset->process) ((dbCommon *)rec);
        dbScanUnlock((dbCommon *)rec);
        return;
    }
    if (get_CIP_typecode(pvt->tag->data) == T_CIP_REAL)
    {
        if (rec->tpro)
            printf("EIP check_ao_callback('%s') w/ real data\n", rec->name);
        if (get_CIP_double(pvt->tag->data, pvt->element, &dbl) &&
            (rec->udf || rec->sevr == INVALID_ALARM || rec->val != dbl))
        {
            if (rec->tpro)
                printf("'%s': got %g from driver\n", rec->name, dbl);
            if (!rec->udf  &&  pvt->special & SPCO_FORCE)
            {
                if (rec->tpro)
                    printf("'%s': will re-write record's value %g\n",
                           rec->name, rec->val);
            }
            else
            {
                rec->val = rec->pval = dbl;
                rec->udf = false;
                if (rec->tpro)
                    printf("'%s': updated record's value %g\n",
                           rec->name, rec->val);
            }
            process = true;
        }
    }
    else
    {
        if (rec->tpro)
            printf("EIP check_ao_callback('%s') w/ int. data\n", rec->name);
        if (get_CIP_DINT(pvt->tag->data, pvt->element, &dint) &&
            (rec->udf || rec->sevr == INVALID_ALARM || rec->rval != dint))
        {
            if (rec->tpro)
                printf("AO '%s': got %ld from driver\n",
                       rec->name, (long)dint);
            if (!rec->udf  &&  pvt->special & SPCO_FORCE)
            {
                if (rec->tpro)
                    printf("AO '%s': will re-write record's rval 0x%X\n",
                           rec->name, (unsigned int)rec->rval);
            }
            else
            {
                /* back-convert raw value into val (copied from ao init) */
                dbl = (double)dint + (double)rec->roff;
                if (rec->aslo!=0.0)
                    dbl *= rec->aslo;
                dbl += rec->aoff;
                switch (rec->linr)
                {
                    case menuConvertNO_CONVERSION:
                        rec->val = rec->pval = dbl;
                        rec->udf = false;
                        break;
                    case menuConvertLINEAR:
                    case menuConvertSLOPE:
                        dbl = dbl*rec->eslo + rec->eoff;
                        rec->val = rec->pval = dbl;
                        rec->udf = false;
                        break;
                    default:
                        if (cvtRawToEngBpt(&dbl,rec->linr,rec->init,
                                           (void *)&rec->pbrk,
                                           &rec->lbrk)!=0)
                            break; /* cannot back-convert */
                        rec->val = rec->pval = dbl;
                        rec->udf = false;
                }
                if (rec->tpro)
                    printf("'%s': updated record's value to %g\n",
                           rec->name, rec->val);
            }
            process = true;
        }
    }
    dbScanUnlock((dbCommon *)rec);
    /* Does record need processing and is not periodic? */
    if (process && rec->scan < SCAN_1ST_PERIODIC)
        scanOnce(rec);
}
Exemple #5
0
static long init_record(aoRecord *prec, int pass)
{
    struct aodset *pdset;
    double 	eoff = prec->eoff, eslo = prec->eslo;
    double	value;

    if (pass==0) return(0);

    /* ao.siml must be a CONSTANT or a PV_LINK or a DB_LINK */
    if (prec->siml.type == CONSTANT) {
	recGblInitConstantLink(&prec->siml,DBF_USHORT,&prec->simm);
    }

    if(!(pdset = (struct aodset *)(prec->dset))) {
	recGblRecordError(S_dev_noDSET,(void *)prec,"ao: init_record");
	return(S_dev_noDSET);
    }
    /* get the initial value if dol is a constant*/
    if (prec->dol.type == CONSTANT) {
	if(recGblInitConstantLink(&prec->dol,DBF_DOUBLE,&prec->val))
	    prec->udf = isnan(prec->val);
    }

    /* must have write_ao function defined */
    if ((pdset->number < 6) || (pdset->write_ao ==NULL)) {
	recGblRecordError(S_dev_missingSup,(void *)prec,"ao: init_record");
	return(S_dev_missingSup);
    }
    prec->init = TRUE;
    /*The following is for old device support that doesnt know about eoff*/
    if ((prec->eslo==1.0) && (prec->eoff==0.0)) {
	prec->eoff = prec->egul;
    }

    if (pdset->init_record) {
	long status=(*pdset->init_record)(prec);
	if (prec->linr == menuConvertSLOPE) {
	    prec->eoff = eoff;
	    prec->eslo = eslo;
	}
        switch(status){
        case(0): /* convert */
	    value = (double)prec->rval + (double)prec->roff;
	    if(prec->aslo!=0.0) value *= prec->aslo;
	    value += prec->aoff;
            if (prec->linr == menuConvertNO_CONVERSION){
		; /*do nothing*/
            } else if ((prec->linr == menuConvertLINEAR) ||
		      (prec->linr == menuConvertSLOPE)) {
                value = value*prec->eslo + prec->eoff;
            }else{
                if(cvtRawToEngBpt(&value,prec->linr,prec->init,
			(void *)&prec->pbrk,&prec->lbrk)!=0) break;
            }
	    prec->val = value;
	    prec->udf = isnan(value);
        break;
        case(2): /* no convert */
        break;
        default:
	     recGblRecordError(S_dev_badInitRet,(void *)prec,"ao: init_record");
	     return(S_dev_badInitRet);
        }
    }
    prec->oval = prec->pval = prec->val;
    prec->mlst = prec->val;
    prec->alst = prec->val;
    prec->lalm = prec->val;
    prec->oraw = prec->rval;
    prec->orbv = prec->rbv;
    return(0);
}