Ejemplo n.º 1
0
static void interruptCallbackInput(void *drvPvt, asynUser *pasynUser, 
                epicsInt32 value)
{
    devInt32Pvt *pPvt = (devInt32Pvt *)drvPvt;
    dbCommon *pr = pPvt->pr;
    int count, size = sizeof(epicsInt32);

    if (pPvt->bipolar && (value & pPvt->signBit)) value |= ~pPvt->mask;
    asynPrint(pPvt->pasynUser, ASYN_TRACEIO_DEVICE,
        "%s devAsynInt32::interruptCallbackInput new value=%d\n",
        pr->name, value);
    /* There is a problem.  A driver could be calling us with a value after
     * this record has registered for callbacks but before EPICS has set interruptAccept,
     * which means that scanIoRequest will return immediately.
     * This is very bad, because if we have pushed a value into the ring buffer
     * it won't get popped off because the record won't process.  The values
     * read the next time the record processes would then be stale.
     * We previously worked around this problem by waiting here for interruptAccept.
     * But that does not work if the callback is coming from the thread that is executing
     * iocInit, which can happen with synchronous drivers (ASYN_CANBLOCK=0) that do callbacks
     * when a value is written to them, which can happen in initRecord for an output record.
     * Instead we just return.  There will then be nothing in the ring buffer, so the first
     * read will do a read from the driver, which should be OK. */
    if (!interruptAccept) return;
    /* Note that we put a lock around epicsRingBytesPut and Get because we potentially have
     * more than one reader, since the reader is whatever thread is processing the record */
    epicsMutexLock(pPvt->mutexId);
    count = epicsRingBytesPut(pPvt->ringBuffer, (char *)&value, size);
    if (count != size) {
        /* There was no room in the ring buffer.  In the past we just threw away
         * the new value.  However, it is better to remove the oldest value from the
         * ring buffer and add the new one.  That way the final value the record receives
         * is guaranteed to be the most recent value */
        epicsInt32 dummy;
        count = epicsRingBytesGet(pPvt->ringBuffer, (char *)&dummy, size);
        if (count != size) {
            asynPrint(pPvt->pasynUser, ASYN_TRACE_ERROR,
                "%s devAsynInt32 interruptCallbackInput error, ring read failed\n",
                pPvt->pr->name);
        }
        count = epicsRingBytesPut(pPvt->ringBuffer, (char *)&value, size);
        if (count != size) {
            asynPrint(pPvt->pasynUser, ASYN_TRACE_ERROR,
                "%s devAsynInt32 interruptCallbackInput error, ring put failed\n",
                pPvt->pr->name);
        }
        pPvt->ringBufferOverflows++;
    } else {
        /* We only need to request the record to process if we added a 
         * new element to the ring buffer, not if we just replaced an element. */
        scanIoRequest(pPvt->ioScanPvt);
    }    
    epicsMutexUnlock(pPvt->mutexId);
}
Ejemplo n.º 2
0
static void interruptCallbackOutput(void *drvPvt, asynUser *pasynUser,
                epicsInt32 value)
{
    devInt32Pvt *pPvt = (devInt32Pvt *)drvPvt;
    dbCommon *pr = pPvt->pr;
    int count, size = sizeof(epicsInt32);

    asynPrint(pPvt->pasynUser, ASYN_TRACEIO_DEVICE,
        "%s devAsynInt32::interruptCallbackOutput new value=%d\n",
        pr->name, value);
    epicsMutexLock(pPvt->mutexId);
    count = epicsRingBytesPut(pPvt->ringBuffer, (char *)&value, size);
    if (count != size) {
        pPvt->ringBufferOverflows++;
    }
    epicsMutexUnlock(pPvt->mutexId);
    scanOnce(pr);
}
Ejemplo n.º 3
0
LOCAL long devBoGP307_write_bo(boRecord *precord)
{
    devGP307dpvt *pdevGP307dpvt = (devGP307dpvt*)precord->dpvt;
    drvGP307Config *pdrvGP307Config = (drvGP307Config*)pdevGP307dpvt->pdrvGP307Config;
    GP307_read *pGP307_read = (GP307_read*) pdrvGP307Config->pGP307_read;
    drvGP307CallbackQueueBuf vdrvGP307CallbackQueueBuf;
    drvGP307CallbackQueueBuf *pdrvGP307CallbackQueueBuf = &vdrvGP307CallbackQueueBuf;
    GP307_read *pBufGP307_read = &pdrvGP307CallbackQueueBuf->vGP307_read;
    int nbytes;
    asynStatus vasynStatus;

    if(precord->pact) {  /* post prcoessing */

        switch(pGP307_read->command_from_postCallback) {
            case GP307CMD_ONDG:
            case GP307CMD_OFFDG:
            case GP307CMD_ONIG0:
            case GP307CMD_OFFIG0:
            case GP307CMD_ONIG1:
            case GP307CMD_OFFIG1:
                break;    /* nothing to do */
            default:
                /* disable record function forever */
                precord->pact = TRUE;
                precord->udf = TRUE;
                return 0;
        }

        precord->udf =FALSE;
        return 2;  /* don't do any conversion */

    }

    /* pre-prcoessing */
    precord->pact = TRUE;

    epicsMutexLock(pdrvGP307Config->lock);
    pdrvGP307Config->cbCount++;
    pBufGP307_read->status = pGP307_read->status;
    epicsMutexUnlock(pdrvGP307Config->lock);
    
    pdrvGP307CallbackQueueBuf->userPvt = (void*)pdrvGP307Config;
    pdrvGP307CallbackQueueBuf->precord = (dbCommon*) precord;

    switch(pdevGP307dpvt->param) {
        case GP307DEVPARAM_DGONOFF:
            if(precord->rval) pdrvGP307CallbackQueueBuf->command = GP307CMD_ONDG;
            else             pdrvGP307CallbackQueueBuf->command = GP307CMD_OFFDG;
            break;
        case GP307DEVPARAM_IG0ONOFF:
            if(precord->rval) pdrvGP307CallbackQueueBuf->command = GP307CMD_ONIG0;
            else             pdrvGP307CallbackQueueBuf->command = GP307CMD_OFFIG0;
            break;
        case GP307DEVPARAM_IG1ONOFF:
            if(precord->rval) pdrvGP307CallbackQueueBuf->command = GP307CMD_ONIG1;
            else             pdrvGP307CallbackQueueBuf->command = GP307CMD_OFFIG1;
            break;
        default:
            /* disable record function forever */
            precord->pact = TRUE;
            precord->udf = TRUE;
            return 0;
    }

    /* put the callback queue */
    nbytes = epicsRingBytesPut(pdrvGP307Config->queueCallbackRingBytesId,
                               (char*)pdrvGP307CallbackQueueBuf,
                               sizeof(drvGP307CallbackQueueBuf)); 
    vasynStatus = pasynManager->queueRequest(pdrvGP307Config->pasynGP307User, asynQueuePriorityLow, pdrvGP307Config->cbTimeout);
    if(vasynStatus == asynError) {
        epicsMutexLock(pdrvGP307Config->lock);
        pdrvGP307Config->asynRequestLostCount++;
        epicsMutexUnlock(pdrvGP307Config->lock);
    }
    return 0;
}
Ejemplo n.º 4
0
LOCAL long devMbbiGP307_read_mbbi(mbbiRecord *precord)
{
    devGP307dpvt *pdevGP307dpvt = (devGP307dpvt*)precord->dpvt;
    drvGP307Config *pdrvGP307Config = (drvGP307Config*)pdevGP307dpvt->pdrvGP307Config;
    GP307_read *pGP307_read = (GP307_read*)pdrvGP307Config->pGP307_read;
    drvGP307CallbackQueueBuf vdrvGP307CallbackQueueBuf;
    drvGP307CallbackQueueBuf *pdrvGP307CallbackQueueBuf = &vdrvGP307CallbackQueueBuf;
    GP307_read *pBufGP307_read = &pdrvGP307CallbackQueueBuf->vGP307_read;
    int nbytes;
    asynStatus vasynStatus;

    if(precord->pact) { /* post processing */
        switch(pGP307_read->command_from_postCallback) {
            case GP307CMD_DGS:
                epicsMutexLock(pdrvGP307Config->lock);
                precord->rval = (pGP307_read->status & GP307STATUS_DGONOFF_MASK)?((unsigned long)0x01):((unsigned long)0x00);
                epicsMutexUnlock(pdrvGP307Config->lock);
                break;
            case GP307CMD_READPCS:
                epicsMutexLock(pdrvGP307Config->lock);
                precord->rval = (unsigned long) pGP307_read->pcs;
                epicsMutexUnlock(pdrvGP307Config->lock);
                break;
            default:
                /* disable record function forever */
                precord->pact = TRUE;
                precord->udf = TRUE;
                return 0;
        }
        precord->val = precord->rval;
        precord->udf = FALSE;
        return 2;       /* don't do any conversion */
    }

    /* pre-processing */
    precord->pact = TRUE;

    epicsMutexLock(pdrvGP307Config->lock);
    pdrvGP307Config->cbCount++;
    pBufGP307_read->status = pGP307_read->status;
    epicsMutexUnlock(pdrvGP307Config->lock);

    pdrvGP307CallbackQueueBuf->userPvt = (void*)pdrvGP307Config;
    pdrvGP307CallbackQueueBuf->precord = (dbCommon*)precord;

    switch(pdevGP307dpvt->param) {
        case GP307DEVPARAM_READDGS:
            pdrvGP307CallbackQueueBuf->command = GP307CMD_DGS;
            break;
        case GP307DEVPARAM_READPCS:
            pdrvGP307CallbackQueueBuf->command = GP307CMD_READPCS;
            break;
        default:
            /* disable record function forever */
            precord->pact = TRUE;
            precord->udf = TRUE;
            return 0;
    }

    /* put the callback queue */
    nbytes = epicsRingBytesPut(pdrvGP307Config->queueCallbackRingBytesId,
                               (char*)pdrvGP307CallbackQueueBuf,
                                sizeof(drvGP307CallbackQueueBuf));
    vasynStatus = pasynManager->queueRequest(pdrvGP307Config->pasynGP307User, asynQueuePriorityLow, pdrvGP307Config->cbTimeout);
    if(vasynStatus == asynError) {
        epicsMutexLock(pdrvGP307Config->lock);
        pdrvGP307Config->asynRequestLostCount++;
        epicsMutexUnlock(pdrvGP307Config->lock);
    }
    return 0; 
}
Ejemplo n.º 5
0
/** This function computes the sums, diffs and positions, and does callbacks 
  * \param[in] raw Array of raw current readings 
  */
void drvQuadEM::computePositions(epicsFloat64 raw[QE_MAX_INPUTS])
{
    int i;
    int count;
    int numAverage;
    int ringOverflows;
    int geometry;
    epicsFloat64 currentOffset[QE_MAX_INPUTS];
    epicsFloat64 currentScale[QE_MAX_INPUTS];
    epicsFloat64 positionOffset[2];
    epicsFloat64 positionScale[2];
    epicsInt32 intData[QE_MAX_DATA];
    epicsFloat64 doubleData[QE_MAX_DATA];
    epicsFloat64 denom;
    static const char *functionName = "computePositions";
    
    getIntegerParam(P_Geometry, &geometry);
    // If the ring buffer is full then remove the oldest entry
    if (epicsRingBytesFreeBytes(ringBuffer_) < (int)sizeof(doubleData)) {
        count = epicsRingBytesGet(ringBuffer_, (char *)&doubleData, sizeof(doubleData));
        ringCount_--;
        getIntegerParam(P_RingOverflows, &ringOverflows);
        ringOverflows++;
        setIntegerParam(P_RingOverflows, ringOverflows);
    }
    
    for (i=0; i<QE_MAX_INPUTS; i++) {
        getDoubleParam(i, P_CurrentOffset, &currentOffset[i]);
        getDoubleParam(i, P_CurrentScale,  &currentScale[i]);
        doubleData[i] = raw[i]*currentScale[i] - currentOffset[i];
    }
    for (i=0; i<2; i++) {
        getDoubleParam(i, P_PositionOffset, &positionOffset[i]);
        getDoubleParam(i, P_PositionScale, &positionScale[i]);
    }
    
    doubleData[QESumAll] = doubleData[QECurrent1] + doubleData[QECurrent2] +
                           doubleData[QECurrent3] + doubleData[QECurrent4];
    if (geometry == QEGeometrySquare) {
        doubleData[QESumX]   = doubleData[QESumAll];
        doubleData[QESumY]   = doubleData[QESumAll];
        doubleData[QEDiffX]  = (doubleData[QECurrent2] + doubleData[QECurrent3]) -
                               (doubleData[QECurrent1] + doubleData[QECurrent4]);
        doubleData[QEDiffY]  = (doubleData[QECurrent1] + doubleData[QECurrent2]) -
                               (doubleData[QECurrent3] + doubleData[QECurrent4]);
    } 
    else {
        doubleData[QESumX]   = doubleData[QECurrent1] + doubleData[QECurrent2];
        doubleData[QESumY]   = doubleData[QECurrent3] + doubleData[QECurrent4];
        doubleData[QEDiffX]  = doubleData[QECurrent2] - doubleData[QECurrent1];
        doubleData[QEDiffY]  = doubleData[QECurrent4] - doubleData[QECurrent3];
    }
    denom = doubleData[QESumX];
    if (denom == 0.) denom = 1.;
    doubleData[QEPositionX] = (positionScale[0] * doubleData[QEDiffX] / denom) -  positionOffset[0];
    denom = doubleData[QESumY];
    if (denom == 0.) denom = 1.;
    doubleData[QEPositionY] = (positionScale[1] * doubleData[QEDiffY] / denom) -  positionOffset[1];

    count = epicsRingBytesPut(ringBuffer_, (char *)&doubleData, sizeof(doubleData));
    ringCount_++;
    if (count != sizeof(doubleData)) {
        asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
               "%s:%s: error writing ring buffer, count=%d, should be %d\n", 
               driverName, functionName, count, (int)sizeof(doubleData));
    }

    getIntegerParam(P_NumAverage, &numAverage);
    if (numAverage > 0) {
        if (ringCount_ >= numAverage) {
            triggerCallbacks();
        }
    }

    for (i=0; i<QE_MAX_DATA; i++) {
        intData[i] = (epicsInt32)doubleData[i];
        setDoubleParam(i, P_DoubleData, doubleData[i]);
        callParamCallbacks(i);
    }
    doCallbacksInt32Array(intData, QE_MAX_DATA, P_IntArrayData, 0);
}