static void initAuxmrWait() { epicsTimeStamp stime,etime; double elapsedTime = 0.0; int ntimes = 1; static int nloops = 1000000; double totalLoops; while(elapsedTime<1.0) { int i; ntimes *= 2; epicsTimeGetCurrent(&stime); for(i=0; i<ntimes; i++) wasteTime(nloops); epicsTimeGetCurrent(&etime); elapsedTime = epicsTimeDiffInSeconds(&etime,&stime); } totalLoops = ((double)ntimes) * ((double)nloops); nloopsPerMicrosecond = (totalLoops/elapsedTime)/1e6 + .99; if(ni1014Debug) { printf("totalLoops %f elapsedTime %f nloopsPerMicrosecond %ld\n", totalLoops,elapsedTime,nloopsPerMicrosecond); epicsTimeGetCurrent(&stime); microSecondDelay(1000000); epicsTimeGetCurrent(&etime); elapsedTime = epicsTimeDiffInSeconds(&etime,&stime); printf("elapsedTime %f\n",elapsedTime); } }
static void myCallback(CALLBACK *pCallback) { myPvt *pmyPvt; epicsTimeStamp now; double delay, error; epicsTimeGetCurrent(&now); callbackGetUser(pmyPvt, pCallback); if (pmyPvt->pass++ == 0) { delay = 0.0; error = epicsTimeDiffInSeconds(&now, &pmyPvt->start); pmyPvt->start = now; callbackRequestDelayed(&pmyPvt->cb2, pmyPvt->delay); } else if (pmyPvt->pass == 2) { double diff = epicsTimeDiffInSeconds(&now, &pmyPvt->start); delay = pmyPvt->delay; error = fabs(delay - diff); } else { testFail("pass = %d for delay = %f", pmyPvt->pass, pmyPvt->delay); return; } testOk(error < 0.05, "delay %f seconds, callback time error %f", delay, error); }
void motorSimController::motorSimTask() { epicsTimeStamp now; double delta; int axis; motorSimAxis *pAxis; while ( 1 ) { /* Get a new timestamp */ epicsTimeGetCurrent( &now ); delta = epicsTimeDiffInSeconds( &now, &(prevTime_) ); prevTime_ = now; if ( delta > (DELTA/4.0) && delta <= (4.0*DELTA) ) { /* A reasonable time has elapsed, it's not a time step in the clock */ for (axis=0; axis<numAxes_; axis++) { this->lock(); pAxis = getAxis(axis); pAxis->process(delta ); this->unlock(); } } epicsThreadSleep( DELTA ); } }
static void harnessExit(void *dummy) { epicsTimeStamp ended; int Faulty; if (!Harness) return; epicsTimeGetCurrent(&ended); printf("\n\n EPICS Test Harness Results" "\n ==========================\n\n"); Faulty = ellCount(&faults); if (!Faulty) printf("All tests successful.\n"); else { int Failures = 0; testFailure *f; printf("Failing Program Tests Faults\n" "---------------------------------------\n"); while ((f = (testFailure *)ellGet(&faults))) { Failures += f->failures; printf("%-25s %5d %5d\n", f->name, f->tests, f->failures); if (f->skips) printf("%d subtests skipped\n", f->skips); free(f); } printf("\nFailed %d/%d test programs. %d/%d subtests failed.\n", Faulty, Programs, Failures, Tests); } printf("Programs=%d, Tests=%d, %.0f wallclock secs\n\n", Programs, Tests, epicsTimeDiffInSeconds(&ended, &started)); }
void Sim::run() { Guard G(lock); while(!stop) { if(!doSim) { UnGuard U(G); event.wait(); continue; } doSim = false; epicsTimeStamp start; epicsTimeGetCurrent(&start); try { std::auto_ptr<StateBase> state(machine->allocState()); machine->propagate(state.get()); valid = true; }catch(std::exception& e){ last_msg = e.what(); valid = false; } epicsTimeGetCurrent(&last_run); last_duration = epicsTimeDiffInSeconds(&last_run, &start); scanIoRequest(aftersim); } }
void drvFastSweep::nextPoint(epicsInt32 *newData) { int i; int offset; epicsTimeStamp now; if (!acquiring_) return; offset = numAcquired_; for (i = 0; i < maxSignals_; i++) { pData_[offset] = newData[i]; offset += maxPoints_; } numAcquired_++; if (numAcquired_ >= numPoints_) { stopAcquire(); } epicsTimeGetCurrent(&now); elapsedTime_ = epicsTimeDiffInSeconds(&now, &startTime_); if ((realTime_ > 0) && (elapsedTime_ >= realTime_)) { stopAcquire(); } setIntegerParam(fastSweepCurrentChannel_, numAcquired_); setDoubleParam(mcaElapsedRealTime_, elapsedTime_); callParamCallbacks(); }
void epicsSpinPerformance () { static const unsigned N = 10000; unsigned i; epicsSpinId spin; epicsTimeStamp begin; epicsTimeStamp end; double delay; /* Initialize spinlock */ spin = epicsSpinCreate(); if (!spin) testAbort("epicsSpinCreate() returned NULL"); /* test a single lock pair */ epicsTimeGetCurrent(&begin); for ( i = 0; i < N; i++ ) { tenLockPairsSquared(spin); } epicsTimeGetCurrent(&end); delay = epicsTimeDiffInSeconds(&end, &begin); delay /= N * 100u; /* convert to delay per lock pair */ delay *= 1e6; /* convert to micro seconds */ testDiag("lock()*1/unlock()*1 takes %f microseconds", delay); epicsSpinDestroy(spin); }
static void motorProcTask( motorSim_t *pDrv) { epicsTimeStamp now; double delta; AXIS_HDL pAxis; /* Get a new timestamp */ epicsTimeGetCurrent( &now ); delta = epicsTimeDiffInSeconds( &now, &(pDrv->now) ); pDrv->now = now; if ( delta > (DELTA/4.0) && delta <= (4.0*DELTA) ) { /* A reasonable time has elapsed, it's not a time step in the clock */ for (pAxis = pDrv->pFirst; pAxis != NULL; pAxis = pAxis->pNext ) { if (epicsMutexLock( pAxis->axisMutex ) == epicsMutexLockOK) { motorSimProcess( pAxis, delta ); motorParam->callCallback( pAxis->params ); epicsMutexUnlock( pAxis->axisMutex ); } } } }
int main(int argc, char **argv) { int i, j, loop; int ignore=0; epicsTimeStamp tStart, tEnd; int status; printf("Initializing ...\n"); xiaSetLogLevel(2); xiaInit("test4.ini"); xiaStartSystem(); for (i=0; i<NUM_SCAS; i++) { sca_lo[i] = calloc(1, SCA_NAME_LEN); sprintf(sca_lo[i], "sca%d_lo", i); sca_hi[i] = calloc(1, SCA_NAME_LEN); sprintf(sca_hi[i], "sca%d_hi", i); } for (loop=0; loop<NUM_LOOPS; loop++) { printf("Loop = %d/%d\n", loop+1, NUM_LOOPS); epicsTimeGetCurrent(&tStart); for (i=0; i<NUM_CHANNELS; i++) { printf(" channel=%d\n", i); for (j=0; j<NUM_SCAS; j++) { setSCAs(i); } } status = xiaBoardOperation(0, "apply", &ignore); CHECK_STATUS(status); epicsTimeGetCurrent(&tEnd); printf("Time = %f\n", epicsTimeDiffInSeconds(&tEnd, &tStart)); } return(0); }
static long read_delta(aiRecord* prec) { epicsMutexMustLock(ntpShm.ntplock); double val = 0.0; if(ntpShm.lastValid) val = epicsTimeDiffInSeconds(&ntpShm.lastStamp, &ntpShm.lastRx); else recGblSetSevr(prec, READ_ALARM, INVALID_ALARM); if(prec->tse==epicsTimeEventDeviceTime) { prec->time = ntpShm.lastStamp; } epicsMutexUnlock(ntpShm.ntplock); if(prec->linr==menuConvertLINEAR){ val-=prec->eoff; if(prec->eslo!=0) val/=prec->eslo; } val-=prec->aoff; if(prec->aslo!=0) val/=prec->aslo; prec->val = val; prec->udf = !isfinite(val); return 2; }
/* print list of stopped records, and breakpoints set in locksets */ long epicsShareAPI dbstat(void) { struct LS_LIST *pnode; struct BP_LIST *pbl; struct EP_LIST *pqe; epicsTimeStamp time; epicsMutexMustLock(bkpt_stack_sem); epicsTimeGetCurrent(&time); /* * Traverse list, reporting stopped records */ pnode = (struct LS_LIST *) ellFirst(&lset_stack); while (pnode != NULL) { if (pnode->precord != NULL) { printf("LSet: %lu Stopped at: %-28.28s #B: %5.5d T: %p\n", pnode->l_num, pnode->precord->name, ellCount(&pnode->bp_list), pnode->taskid); /* for each entrypoint detected, print out entrypoint statistics */ pqe = (struct EP_LIST *) ellFirst(&pnode->ep_queue); while (pqe != NULL) { double diff = epicsTimeDiffInSeconds(&time,&pqe->time); if (diff) { printf(" Entrypoint: %-28.28s #C: %5.5lu C/S: %7.1f\n", pqe->entrypoint->name, pqe->count,diff); } pqe = (struct EP_LIST *) ellNext((ELLNODE *)pqe); } } else { printf("LSet: %lu #B: %5.5d T: %p\n", pnode->l_num, ellCount(&pnode->bp_list), pnode->taskid); } /* * Print out breakpoints set in the lock set */ pbl = (struct BP_LIST *) ellFirst(&pnode->bp_list); while (pbl != NULL) { printf(" Breakpoint: %-28.28s", pbl->precord->name); /* display auto print flag */ if (pbl->precord->bkpt & BKPT_PRINT_MASK) printf(" (ap)\n"); else printf("\n"); pbl = (struct BP_LIST *) ellNext((ELLNODE *)pbl); } pnode = (struct LS_LIST *) ellNext((ELLNODE *)pnode); } epicsMutexUnlock(bkpt_stack_sem); return(0); }
int devIocStatsInitCpuUsage(void) { int nBurnNoContention = 0; double tToWait = SECONDS_TO_BURN; epicsTimeStamp tStart, tEnd; if (cpuUsage.startSem) return 0; /* Initialize only if OS wants to spin */ if (tToWait > 0) { /*wait for a tick*/ epicsTimeGetCurrent(&tStart); do { epicsTimeGetCurrent(&tEnd); } while ( epicsTimeDiffInSeconds(&tEnd, &tStart) <= 0.0 ); epicsTimeGetCurrent(&tStart); while(TRUE) { cpuBurn(); epicsTimeGetCurrent(&tEnd); cpuUsage.tNow = epicsTimeDiffInSeconds(&tEnd, &tStart); if (cpuUsage.tNow >= tToWait ) break; nBurnNoContention++; } cpuUsage.nBurnNoContention = nBurnNoContention; cpuUsage.nBurnNow = nBurnNoContention; cpuUsage.startSem = epicsEventMustCreate(epicsEventFull); cpuUsage.tNoContention = cpuUsage.tNow; /* * FIXME: epicsThreadPriorityMin is not really the lowest * priority. We could use a native call to * lower our priority further but OTOH there is not * much going on at these low levels... */ epicsThreadCreate("cpuUsageTask", epicsThreadPriorityMin, epicsThreadGetStackSize(epicsThreadStackMedium), (EPICSTHREADFUNC)cpuUsageTask, 0); } else { cpuUsage.startSem = 0; } return 0; }
/* * clean_addrq */ static void clean_addrq(void) { struct channel_in_use * pciu; struct channel_in_use * pnextciu; epicsTimeStamp current; double delay; double maxdelay = 0; unsigned ndelete=0; double timeout = TIMEOUT; int s; epicsTimeGetCurrent ( ¤t ); epicsMutexMustLock ( prsrv_cast_client->chanListLock ); pnextciu = (struct channel_in_use *) prsrv_cast_client->chanList.node.next; while( (pciu = pnextciu) ) { pnextciu = (struct channel_in_use *)pciu->node.next; delay = epicsTimeDiffInSeconds(¤t,&pciu->time_at_creation); if (delay > timeout) { ellDelete(&prsrv_cast_client->chanList, &pciu->node); LOCK_CLIENTQ; s = bucketRemoveItemUnsignedId ( pCaBucket, &pciu->sid); if(s){ errMessage (s, "Bad id at close"); } else { rsrvChannelCount--; } UNLOCK_CLIENTQ; if ( ! s ) { freeListFree(rsrvChanFreeList, pciu); ndelete++; } if(delay>maxdelay) maxdelay = delay; } } epicsMutexUnlock ( prsrv_cast_client->chanListLock ); # ifdef DEBUG if(ndelete){ epicsPrintf ("CAS: %d CA channels have expired after %f sec\n", ndelete, maxdelay); } # endif }
static double cpuBurn(void) { epicsTimeStamp then, now; double diff; /* poll the clock for 500us */ epicsTimeGetCurrent(&then); do { epicsTimeGetCurrent(&now); diff = epicsTimeDiffInSeconds(&now,&then); } while ( diff < 0.0005 ); return diff; }
void vxStats_busyloop(unsigned busyperc) { epicsTimeStamp then, now; double fac = vxStats_busyloop_period/(double)100.0; if ( busyperc > 100 ) busyperc = 100; while ( vxStats_busyloop_run ) { epicsTimeGetCurrent(&then); do { epicsTimeGetCurrent(&now); } while ( epicsTimeDiffInSeconds(&now,&then) < (double)busyperc*fac ); epicsThreadSleep((double)(100-busyperc)*fac); } }
int Eiger::waitFile (const char *filename, double timeout) { const char *functionName = "waitFile"; epicsTimeStamp start, now; request_t request; char requestBuf[MAX_MESSAGE_SIZE]; request.data = requestBuf; request.dataLen = sizeof(requestBuf); request.actualLen = epicsSnprintf(request.data, request.dataLen, REQUEST_HEAD, sysStr[SSData], filename); response_t response; char responseBuf[MAX_MESSAGE_SIZE]; response.data = responseBuf; response.dataLen = sizeof(responseBuf); epicsTimeGetCurrent(&start); do { if(doRequest(&request, &response)) { ERR_ARGS("[file=%s] HEAD request failed", filename); return EXIT_FAILURE; } if(response.code == 200) return EXIT_SUCCESS; if(response.code != 404) { ERR_ARGS("[file=%s] server returned error code %d", filename, response.code); return EXIT_FAILURE; } epicsTimeGetCurrent(&now); }while(epicsTimeDiffInSeconds(&now, &start) < timeout); //ERR_ARGS("timeout waiting for file %s", filename); return EXIT_FAILURE; }
static void cpuUsageTask(void *parm) { while(TRUE) { int i; epicsTimeStamp tStart, tEnd; epicsEventWait(cpuUsage.startSem); cpuUsage.nBurnNow=0; epicsTimeGetCurrent(&tStart); for(i=0; i< cpuUsage.nBurnNoContention; i++) { cpuBurn(); epicsTimeGetCurrent(&tEnd); cpuUsage.tNow = epicsTimeDiffInSeconds(&tEnd, &tStart); ++cpuUsage.nBurnNow; } cpuUsage.didNotComplete = FALSE; } }
int Eiger::trigger (int timeout, double exposure) { // Trigger for INTS mode if(!exposure) return put(SSCommand, "trigger", "", 0, NULL, timeout); // Tigger for INTE mode // putDouble should block for the whole exposure duration, but it doesn't // (Eiger's fault) epicsTimeStamp start, end; epicsTimeGetCurrent(&start); if(putDouble(SSCommand, "trigger", exposure, NULL, timeout)) return EXIT_FAILURE; epicsTimeGetCurrent(&end); double diff = epicsTimeDiffInSeconds(&end, &start); if(diff < exposure) epicsThreadSleep(exposure - diff); return EXIT_SUCCESS; }
asynStatus mar345::waitForCompletion(const char *doneString, double timeout) { char response[MAX_MESSAGE_SIZE]; asynStatus status; double elapsedTime; epicsTimeStamp start, now; const char *functionName = "waitForCompletion"; epicsTimeGetCurrent(&start); while (1) { status = readServer(response, sizeof(response), MAR345_POLL_DELAY); if (status == asynSuccess) { if (strstr(response, doneString)) return(asynSuccess); } epicsTimeGetCurrent(&now); elapsedTime = epicsTimeDiffInSeconds(&now, &start); if (elapsedTime > timeout) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: error waiting for response from marServer\n", driverName, functionName); return(asynError); } } }
/* * Write to the TCP port */ static asynStatus writeIt(void *drvPvt, asynUser *pasynUser, const char *data, size_t numchars,size_t *nbytesTransfered) { ttyController_t *tty = (ttyController_t *)drvPvt; int thisWrite; asynStatus status = asynSuccess; int writePollmsec; int epicsTimeStatus; epicsTimeStamp startTime; epicsTimeStamp endTime; int haveStartTime; assert(tty); asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s write.\n", tty->IPDeviceName); asynPrintIO(pasynUser, ASYN_TRACEIO_DRIVER, data, numchars, "%s write %lu\n", tty->IPDeviceName, (unsigned long)numchars); *nbytesTransfered = 0; if (tty->fd == INVALID_SOCKET) { if (tty->flags & FLAG_CONNECT_PER_TRANSACTION) { if ((status = connectIt(drvPvt, pasynUser)) != asynSuccess) return status; } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "%s disconnected:", tty->IPDeviceName); return asynError; } } if (numchars == 0) return asynSuccess; writePollmsec = (int) (pasynUser->timeout * 1000.0); if (writePollmsec == 0) writePollmsec = 1; if (writePollmsec < 0) writePollmsec = -1; #ifdef USE_SOCKTIMEOUT { struct timeval tv; tv.tv_sec = writePollmsec / 1000; tv.tv_usec = (writePollmsec % 1000) * 1000; if (setsockopt(tty->fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof tv) < 0) { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Can't set %s socket send timeout: %s", tty->IPDeviceName, strerror(SOCKERRNO)); return asynError; } } #endif haveStartTime = 0; for (;;) { #ifdef USE_POLL struct pollfd pollfd; pollfd.fd = tty->fd; pollfd.events = POLLOUT; epicsTimeGetCurrent(&startTime); while (poll(&pollfd, 1, writePollmsec) < 0) { if (errno != EINTR) { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Poll() failed: %s", strerror(errno)); return asynError; } epicsTimeGetCurrent(&endTime); if (epicsTimeDiffInSeconds(&endTime, &startTime)*1000 > writePollmsec) break; } #endif for (;;) { if (tty->socketType == SOCK_DGRAM) { thisWrite = sendto(tty->fd, (char *)data, (int)numchars, 0, &tty->farAddr.oa.sa, (int)tty->farAddrSize); } else { thisWrite = send(tty->fd, (char *)data, (int)numchars, 0); } if (thisWrite >= 0) break; if (SOCKERRNO == SOCK_EWOULDBLOCK || SOCKERRNO == SOCK_EINTR) { if (!haveStartTime) { epicsTimeStatus = epicsTimeGetCurrent(&startTime); assert(epicsTimeStatus == epicsTimeOK); haveStartTime = 1; } else if (pasynUser->timeout >= 0) { epicsTimeStatus = epicsTimeGetCurrent(&endTime); assert(epicsTimeStatus == epicsTimeOK); if (epicsTimeDiffInSeconds(&endTime, &startTime) > pasynUser->timeout) { thisWrite = 0; break; } } epicsThreadSleep(SEND_RETRY_DELAY); } else break; } if (thisWrite > 0) { tty->nWritten += (unsigned long)thisWrite; *nbytesTransfered += thisWrite; numchars -= thisWrite; if (numchars == 0) break; data += thisWrite; } else if (thisWrite == 0) { status = asynTimeout; break; } else { epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize, "%s write error: %s", tty->IPDeviceName, strerror(SOCKERRNO)); closeConnection(pasynUser,tty,"Write error"); status = asynError; break; } } asynPrint(pasynUser, ASYN_TRACE_FLOW, "wrote %lu to %s, return %s.\n", (unsigned long)*nbytesTransfered, tty->IPDeviceName, pasynManager->strStatus(status)); return status; }
static asynStatus AIMWrite(void *drvPvt, asynUser *pasynUser, epicsInt32 ivalue, epicsFloat64 dvalue) { mcaAIMPvt *pPvt = (mcaAIMPvt *)drvPvt; mcaCommand command=pasynUser->reason; asynStatus status=asynSuccess; int len; int address, seq; int signal; epicsTimeStamp now; pasynManager->getAddr(pasynUser, &signal); asynPrint(pasynUser, ASYN_TRACE_FLOW, "mcaAIMAsynDriver::AIMWrite entry, command=%d, signal=%d, " "ivalue=%d, dvalue=%f\n", command, signal, ivalue, dvalue); switch (command) { case mcaStartAcquire: /* Start acquisition. */ status = nmc_acqu_setstate(pPvt->module, pPvt->adc, 1); break; case mcaStopAcquire: /* stop data acquisition */ status = nmc_acqu_setstate(pPvt->module, pPvt->adc, 0); break; case mcaErase: /* Erase. If this is signal 0 then erase memory for all signals. * Databases take advantage of this for performance with * multielement detectors with multiplexors */ if (signal == 0) len = pPvt->maxChans*pPvt->maxSignals*4; else len = pPvt->nchans*4; /* If AIM is acquiring, turn if off */ if (pPvt->acquiring) status = nmc_acqu_setstate(pPvt->module, pPvt->adc, 0); address = pPvt->seq_address + pPvt->maxChans*signal*4; status = nmc_acqu_erase(pPvt->module, address, len); asynPrint(pasynUser, ASYN_TRACE_FLOW, "(mcaAIMAsynDriver::command [%s signal=%d]):" " erased %d chans, status=%d\n", pPvt->portName, signal, len, status); /* Set the elapsed live and real time back to zero. */ status = nmc_acqu_setelapsed(pPvt->module, pPvt->adc, 0, 0); /* If AIM was acquiring, turn it back on */ if (pPvt->acquiring) status = nmc_acqu_setstate(pPvt->module, pPvt->adc, 1); break; case mcaReadStatus: /* The status will be the same for each signal on a port. * We optimize by not reading the status if this is not * signal 0 and if the cached status is relatively recent * Read the current status of the device if signal 0 or * if the existing status info is too old */ epicsTimeGetCurrent(&now); if ((signal == 0) || (epicsTimeDiffInSeconds(&now, &pPvt->statusTime) > pPvt->maxStatusTime)) { status = nmc_acqu_statusupdate(pPvt->module, pPvt->adc, 0, 0, 0, &pPvt->elive, &pPvt->ereal, &pPvt->etotals, &pPvt->acquiring); asynPrint(pasynUser, ASYN_TRACE_FLOW, "(mcaAIMAsynDriver [%s signal=%d]): get_acq_status=%d\n", pPvt->portName, signal, status); epicsTimeGetCurrent(&pPvt->statusTime); } case mcaChannelAdvanceSource: /* set channel advance source */ /* This is a NOOP for current MCS hardware - done manually */ break; case mcaNumChannels: /* set number of channels */ pPvt->nchans = ivalue; if (pPvt->nchans > pPvt->maxChans) { asynPrint(pasynUser, ASYN_TRACE_ERROR, "mcaAIMServer Illegal nuse field"); pPvt->nchans = pPvt->maxChans; } status = sendAIMSetup(pPvt); break; case mcaAcquireMode: if (ivalue == mcaAcquireMode_PHA) pPvt->acqmod = 1; if (ivalue == mcaAcquireMode_MCS) pPvt->acqmod = 1; if (ivalue == mcaAcquireMode_List) pPvt->acqmod = 3; status = sendAIMSetup(pPvt); break; case mcaSequence: /* set sequence number */ seq = ivalue; if (seq > pPvt->maxSequences) { asynPrint(pasynUser, ASYN_TRACE_ERROR, "mcaAIMAsynDriver::command: Illegal seq field\n"); seq = pPvt->maxSequences; } pPvt->seq_address = pPvt->base_address + pPvt->maxChans * pPvt->maxSignals * seq * 4; status = sendAIMSetup(pPvt); break; case mcaPrescale: /* No-op for AIM */ break; case mcaPresetSweeps: /* set number of sweeps (for MCS mode) */ /* This is a NOOP on current version of MCS */ break; case mcaPresetLowChannel: /* set lower side of region integrated for preset counts */ /* The preset total start channel is in bytes from start of AIM memory */ pPvt->ptschan = pPvt->seq_address + pPvt->maxChans*signal*4 + ivalue*4; status = sendAIMSetup(pPvt); break; case mcaPresetHighChannel: /* set high side of region integrated for preset counts */ /* The preset total end channel is in bytes from start of AIM memory */ pPvt->ptechan = pPvt->seq_address + pPvt->maxChans*signal*4 + ivalue*4; status = sendAIMSetup(pPvt); break; case mcaDwellTime: /* set dwell time */ /* This is a NOOP for current MCS hardware - done manually */ break; case mcaPresetRealTime: /* set preset real time. Convert to centiseconds */ pPvt->preal = (int) (100. * dvalue); status = sendAIMSetup(pPvt); break; case mcaPresetLiveTime: /* set preset live time. Convert to centiseconds */ pPvt->plive = (int) (100. * dvalue); status = sendAIMSetup(pPvt); break; case mcaPresetCounts: /* set preset counts */ pPvt->ptotal = dvalue; status = sendAIMSetup(pPvt); break; default: asynPrint(pasynUser, ASYN_TRACE_ERROR, "mcaAIMAsynDriver::command port %s got illegal command %d\n", pPvt->portName, command); break; } return(asynSuccess); }
/** This thread is woken up by an interrupt or a request to read status * It loops calling readFIFO until acquiring_ goes to false. * readFIFO only reads a limited amount of FIFO data at once in order * to avoid blocking the device support threads. */ void drvSIS3801::readFIFOThread() { int count; int signal; int chan; int nChans; int status; int i; bool acquiring; // We have a separate flag because we need to continue processing one last // time even if acquiring_ goes to false because acquisition was manually stopped epicsUInt32 scalerPresets[SIS38XX_MAX_SIGNALS]; epicsUInt32 *pOut=NULL; epicsTimeStamp t1, t2; static const char* functionName="readFIFOThread"; while(true) { epicsEventWait(readFIFOEventId_); // We got an event, which can come from acquisition starting, or FIFO full interrupt asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: got readFIFOEvent, eventType=%d, interrupt status=0x%8.8x\n", driverName, functionName, eventType_, registers_->csr_reg & 0xFFF00000); lock(); acquiring = acquiring_; unlock(); while (acquiring) { lock(); for (i=0; i<maxSignals_; i++) getIntegerParam(i, scalerPresets_, (int *)&scalerPresets[i]); getIntegerParam(mcaNumChannels_, &nChans); asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: scaler presets[0]=%d, scalerData[0]=%d\n", driverName, functionName, scalerPresets[0], scalerData_[0]); signal = nextSignal_; chan = nextChan_; count = 0; // This block of code can be slow and does not require the asynPortDriver lock because we are not // accessing object data that could change. // It does require the FIFO lock so no one resets the FIFO while it executes epicsMutexLock(fifoLockId_); unlock(); epicsTimeGetCurrent(&t1); /* Read out FIFO. It would be more efficient not to check the empty * flag on each transfer, using the almost empty flag. But this has gotten * too complex, and is unlikely to save time on new boards with lots of * memory. */ if (acquireMode_== ACQUIRE_MODE_MCS) { // Copy the data from the FIFO to the mcsBuffer pOut = mcsData_ + signal*maxChans_ + chan; asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: pOut=%p, signal=%d, chan=%d\n", driverName, functionName, pOut, signal, chan); while (((registers_->csr_reg & STATUS_M_FIFO_FLAG_EMPTY)==0) && (chan < nChans) && acquiring_) { *pOut = registers_->fifo_reg; signal++; count++; if (signal >= maxSignals_) { signal = 0; chan++; pOut = mcsData_ + chan; } else { pOut += maxChans_; } } } else if (acquireMode_ == ACQUIRE_MODE_SCALER) { while ((registers_->csr_reg & STATUS_M_FIFO_FLAG_EMPTY)==0 && acquiring_) { scalerData_[signal] += registers_->fifo_reg; signal++; count++; if (signal >= maxSignals_) { for (i=0; i<maxSignals_; i++) { if ((scalerPresets[i] != 0) && (scalerData_[i] >= scalerPresets[i])) acquiring = false; } asynPrintIO(pasynUserSelf, ASYN_TRACEIO_DRIVER, (const char*)scalerData_, maxSignals_*sizeof(epicsUInt32), "%s:%s:\n", driverName, functionName); if (!acquiring) break; signal = 0; } } } epicsTimeGetCurrent(&t2); asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: read FIFO (%d) in %fs, acquiring=%d\n", driverName, functionName, count, epicsTimeDiffInSeconds(&t2, &t1), acquiring_); // Release the FIFO lock, we are done accessing the FIFO epicsMutexUnlock(fifoLockId_); // Take the lock since we are now changing object data lock(); nextChan_ = chan; nextSignal_ = signal; if (acquireMode_ == ACQUIRE_MODE_MCS) { asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: pOut=%p,signal=%d, chan=%d\n", driverName, functionName, pOut, signal, chan); checkMCSDone(); } else if (acquireMode_ == ACQUIRE_MODE_SCALER) { if (!acquiring) acquiring_ = false; if (!acquiring_) { asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: scaler done, doing callbacks\n", driverName, functionName); stopScaler(); setIntegerParam(scalerDone_, 1); callParamCallbacks(); } } /* Reenable interrupts in case we were woken up by an interrupt for FIFO almost full */ enableInterrupts(); acquiring = acquiring_; // Release the lock unlock(); // If we are still acquiring then sleep for a short time, but wake up if there is an interrupt if (acquiring) { status = epicsEventWaitWithTimeout(readFIFOEventId_, epicsThreadSleepQuantum()); if (status == epicsEventWaitOK) asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: got interrupt in epicsEventWaitWithTimeout, eventType=%d\n", driverName, functionName, eventType_); } } } }
/* * logClientDestroy */ static void logClientDestroy (logClientId id) { enum epicsSocketSystemCallInterruptMechanismQueryInfo interruptInfo; logClient *pClient = (logClient *) id; epicsTimeStamp begin, current; double diff; /* command log client thread to shutdown - taking mutex here */ /* forces cache flush on SMP machines */ epicsMutexMustLock ( pClient->mutex ); pClient->shutdown = 1u; epicsMutexUnlock ( pClient->mutex ); /* unblock log client thread blocking in send() or connect() */ interruptInfo = epicsSocketSystemCallInterruptMechanismQuery (); switch ( interruptInfo ) { case esscimqi_socketCloseRequired: logClientClose ( pClient ); break; case esscimqi_socketBothShutdownRequired: shutdown ( pClient->sock, SHUT_WR ); break; case esscimqi_socketSigAlarmRequired: epicsSignalRaiseSigAlarm ( pClient->restartThreadId ); break; default: break; }; /* wait for confirmation that the thread exited - taking */ /* mutex here forces cache update on SMP machines */ epicsTimeGetCurrent ( & begin ); epicsMutexMustLock ( pClient->mutex ); do { epicsMutexUnlock ( pClient->mutex ); epicsEventWaitWithTimeout ( pClient->stateChangeNotify, LOG_SERVER_SHUTDOWN_TIMEOUT / 10.0 ); epicsTimeGetCurrent ( & current ); diff = epicsTimeDiffInSeconds ( & current, & begin ); epicsMutexMustLock ( pClient->mutex ); } while ( ! pClient->shutdownConfirm && diff < LOG_SERVER_SHUTDOWN_TIMEOUT ); epicsMutexUnlock ( pClient->mutex ); if ( ! pClient->shutdownConfirm ) { fprintf ( stderr, "log client shutdown: timed out stopping" " reconnect thread for \"%s\" after %.1f seconds - cleanup aborted\n", pClient->name, LOG_SERVER_SHUTDOWN_TIMEOUT ); return; } logClientClose ( pClient ); epicsMutexDestroy ( pClient->mutex ); epicsEventDestroy ( pClient->stateChangeNotify ); free ( pClient ); }
/* * log_one_client () */ static void log_one_client (struct client *client, unsigned level) { char *pproto; double send_delay; double recv_delay; char *state[] = {"up", "down"}; epicsTimeStamp current; char clientHostName[256]; ipAddrToDottedIP (&client->addr, clientHostName, sizeof(clientHostName)); if(client->proto == IPPROTO_UDP){ pproto = "UDP"; } else if(client->proto == IPPROTO_TCP){ pproto = "TCP"; } else{ pproto = "UKN"; } epicsTimeGetCurrent(¤t); send_delay = epicsTimeDiffInSeconds(¤t,&client->time_at_last_send); recv_delay = epicsTimeDiffInSeconds(¤t,&client->time_at_last_recv); printf ( "%s %s(%s): User=\"%s\", V%u.%u, %d Channels, Priority=%u\n", pproto, clientHostName, client->pHostName ? client->pHostName : "", client->pUserName ? client->pUserName : "", CA_MAJOR_PROTOCOL_REVISION, client->minor_version_number, ellCount(&client->chanList) + ellCount(&client->chanPendingUpdateARList), client->priority ); if ( level >= 1 ) { printf ("\tTask Id=%p, Socket FD=%d\n", (void *) client->tid, client->sock); printf( "\tSecs since last send %6.2f, Secs since last receive %6.2f\n", send_delay, recv_delay); printf( "\tUnprocessed request bytes=%u, Undelivered response bytes=%u\n", client->recv.cnt - client->recv.stk, client->send.stk ); printf( "\tState=%s%s%s\n", state[client->disconnect?1:0], client->send.type == mbtLargeTCP ? " jumbo-send-buf" : "", client->recv.type == mbtLargeTCP ? " jumbo-recv-buf" : ""); } if ( level >= 2u ) { unsigned bytes_reserved = 0; bytes_reserved += sizeof(struct client); bytes_reserved += countChanListBytes ( client, & client->chanList ); bytes_reserved += countChanListBytes ( client, & client->chanPendingUpdateARList ); printf( "\t%d bytes allocated\n", bytes_reserved); showChanList ( client, & client->chanList ); showChanList ( client, & client->chanPendingUpdateARList ); printf("\n"); } if ( level >= 3u ) { printf( "\tSend Lock\n"); epicsMutexShow(client->lock,1); printf( "\tPut Notify Lock\n"); epicsMutexShow (client->putNotifyLock,1); printf( "\tAddress Queue Lock\n"); epicsMutexShow (client->chanListLock,1); printf( "\tEvent Queue Lock\n"); epicsMutexShow (client->eventqLock,1); printf( "\tBlock Semaphore\n"); epicsEventShow (client->blockSem,1); } }
static long histScalerDma_do(aSubRecord *pasub) { int j; epicsUInt32 *data; epicsTimeStamp timeStart, timeEnd; double dmaTime; struct dma_proxy_channel_interface *hs_rx_proxy_interface_p; int hs_rx_proxy_fd; int dummy = 0; int timeout_msecs = 10; int dma_bytes; /* in bytes32-byte events */ int dma_words; int *clear = (int *)pasub->d; epicsUInt32 *counts1 = (epicsUInt32 *)pasub->vala; int i; int *debug = (int *)pasub->h; if (*debug>1) { printf("histScalerDma_do: entry\n"); } if (*clear) { /* erase pixel maps */ for (i=0; i<pasub->nova; i++) { counts1[i] = 0; } *histClear = 0x20; *histClear = 0; *clear = 0; } /* cause HistScal component to dump its data to the FIFO */ *histRead = 0x20; *histRead = 0; dma_words = *histScalerDmaWords; dma_bytes = dma_words*4; if (*hs_fifoCountAddr < dma_words) { if (*debug>1) { printf("histScalerDma_do: avail words (%d) < dma_words (%d)\n", *hs_fifoCountAddr, dma_words); } return(0); } /* do DMA */ hs_rx_proxy_fd = open("/dev/dma_proxy_rx", O_RDWR); if (hs_rx_proxy_fd < 1) { printf("histScalerDmaRoutine: Unable to open DMA proxy device file for RX\n"); return(0); } hs_rx_proxy_interface_p = (struct dma_proxy_channel_interface *)mmap(NULL, sizeof(struct dma_proxy_channel_interface), PROT_READ | PROT_WRITE, MAP_SHARED, hs_rx_proxy_fd, 0); if (hs_rx_proxy_interface_p == MAP_FAILED) { printf("histScalerDmaRoutine: Failed to mmap for RX\n"); return(0); } hs_rx_proxy_interface_p->length = dma_bytes; hs_rx_proxy_interface_p->timeout_msecs = timeout_msecs; dmaTime = 0; /* Perform the DMA transfer and after it finishes check the status */ epicsTimeGetCurrent(&timeStart); ioctl(hs_rx_proxy_fd, 0, &dummy); if (*debug && (hs_rx_proxy_interface_p->status != PROXY_NO_ERROR)) { printf("histScalerDmaRoutine: Proxy rx transfer error\n"); munmap(hs_rx_proxy_interface_p, sizeof(struct dma_proxy_channel_interface)); close(hs_rx_proxy_fd); return(0); } data = (epicsUInt32 *)(hs_rx_proxy_interface_p->buffer); epicsTimeGetCurrent(&timeEnd); dmaTime += epicsTimeDiffInSeconds(&timeEnd, &timeStart); /*** collect data ***/ for (j=0; j<dma_words; j++) { counts1[j] = data[j] & 0x7fffffff; if (*debug > 10) printf("histScalerDmaRoutine: counts1[%d]=%d, first==%d\n", j, counts1[j], (data[j] & 0x80000000)!=0); *clear = 0; } /* If there's enough data in the FIFO, do another DMA transaction. */ if (*debug > 1) printf("histScalerDmaRoutine: *hs_fifoCountAddr=%d\n", *hs_fifoCountAddr); if (*debug) printf("histScalerDmaRoutine: DMA time=%f\n", dmaTime); if (*debug>=10) printf("histScalerDmaRoutine: done binning this buffer.\n"); /* For now, just open and close every time */ munmap(hs_rx_proxy_interface_p, sizeof(struct dma_proxy_channel_interface)); close(hs_rx_proxy_fd); return(0); }
static void NTPTimeSync(void *dummy) { taskwdInsert(0, NULL, NULL); for (epicsEventWaitWithTimeout(NTPTimePvt.loopEvent, NTPTimeSyncInterval); NTPTimePvt.synchronize; epicsEventWaitWithTimeout(NTPTimePvt.loopEvent, NTPTimeSyncInterval)) { int status; struct timespec timespecNow; epicsTimeStamp timeNow; epicsUInt32 tickNow; double diff; double ntpDelta; status = osdNTPGet(×pecNow); tickNow = osdTickGet(); if (status) { if (++NTPTimePvt.syncsFailed > NTPTimeSyncRetries && NTPTimePvt.synchronized) { errlogPrintf("NTPTimeSync: NTP requests failing - %s\n", strerror(errno)); NTPTimePvt.synchronized = 0; } continue; } if (timespecNow.tv_sec <= POSIX_TIME_AT_EPICS_EPOCH || epicsTimeFromTimespec(&timeNow, ×pecNow) == epicsTimeERROR) { errlogPrintf("NTPTimeSync: Bad time received from NTP server\n"); NTPTimePvt.synchronized = 0; continue; } ntpDelta = epicsTimeDiffInSeconds(&timeNow, &NTPTimePvt.syncTime); if (ntpDelta <= 0.0 && NTPTimePvt.synchronized) { errlogPrintf("NTPTimeSync: NTP time not increasing, delta = %g\n", ntpDelta); NTPTimePvt.synchronized = 0; continue; } NTPTimePvt.syncsFailed = 0; if (!NTPTimePvt.synchronized) { errlogPrintf("NTPTimeSync: Sync recovered.\n"); } epicsMutexMustLock(NTPTimePvt.lock); diff = epicsTimeDiffInSeconds(&timeNow, &NTPTimePvt.clockTime); if (diff >= 0.0) { NTPTimePvt.ticksToSkip = 0; } else { /* dont go back in time */ NTPTimePvt.ticksToSkip = -diff * osdTickRateGet(); } NTPTimePvt.clockTick = tickNow; NTPTimePvt.clockTime = timeNow; NTPTimePvt.synchronized = 1; epicsMutexUnlock(NTPTimePvt.lock); NTPTimePvt.tickRate = (tickNow - NTPTimePvt.syncTick) / ntpDelta; NTPTimePvt.syncTick = tickNow; NTPTimePvt.syncTime = timeNow; } NTPTimePvt.synchronized = 0; taskwdRemove(0); }
/* * Read from the TCP port */ static asynStatus readIt(void *drvPvt, asynUser *pasynUser, char *data, size_t maxchars,size_t *nbytesTransfered,int *gotEom) { ttyController_t *tty = (ttyController_t *)drvPvt; int thisRead; int readPollmsec; int reason = 0; epicsTimeStamp startTime; epicsTimeStamp endTime; asynStatus status = asynSuccess; assert(tty); asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s read.\n", tty->IPDeviceName); if (tty->fd == INVALID_SOCKET) { if (tty->flags & FLAG_CONNECT_PER_TRANSACTION) { if ((status = connectIt(drvPvt, pasynUser)) != asynSuccess) return status; } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "%s disconnected:", tty->IPDeviceName); return asynError; } } if (maxchars <= 0) { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "%s maxchars %d. Why <=0?",tty->IPDeviceName,(int)maxchars); return asynError; } readPollmsec = (int) (pasynUser->timeout * 1000.0); if (readPollmsec == 0) readPollmsec = 1; if (readPollmsec < 0) readPollmsec = -1; #ifdef USE_SOCKTIMEOUT { struct timeval tv; tv.tv_sec = readPollmsec / 1000; tv.tv_usec = (readPollmsec % 1000) * 1000; if (setsockopt(tty->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv) < 0) { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Can't set %s socket receive timeout: %s", tty->IPDeviceName, strerror(SOCKERRNO)); status = asynError; } } #endif if (gotEom) *gotEom = 0; #ifdef USE_POLL { struct pollfd pollfd; pollfd.fd = tty->fd; pollfd.events = POLLIN; epicsTimeGetCurrent(&startTime); while (poll(&pollfd, 1, readPollmsec) < 0) { if (errno != EINTR) { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "Poll() failed: %s", strerror(errno)); return asynError; } epicsTimeGetCurrent(&endTime); if (epicsTimeDiffInSeconds(&endTime, &startTime)*1000. > readPollmsec) break; } } #endif if (tty->socketType == SOCK_DGRAM) { /* We use recvfrom() for SOCK_DRAM so we can print the source address with ASYN_TRACEIO_DRIVER */ osiSockAddr oa; unsigned int addrlen = sizeof(oa.ia); thisRead = recvfrom(tty->fd, data, (int)maxchars, 0, &oa.sa, &addrlen); if (thisRead > 0) { if (pasynTrace->getTraceMask(pasynUser) & ASYN_TRACEIO_DRIVER) { char inetBuff[32]; ipAddrToDottedIP(&oa.ia, inetBuff, sizeof(inetBuff)); asynPrintIO(pasynUser, ASYN_TRACEIO_DRIVER, data, thisRead, "%s (from %s) read %d\n", tty->IPDeviceName, inetBuff, thisRead); } tty->nRead += (unsigned long)thisRead; } } else { thisRead = recv(tty->fd, data, (int)maxchars, 0); if (thisRead > 0) { asynPrintIO(pasynUser, ASYN_TRACEIO_DRIVER, data, thisRead, "%s read %d\n", tty->IPDeviceName, thisRead); tty->nRead += (unsigned long)thisRead; } } if (thisRead < 0) { int should_close = (tty->userFlags & USERFLAG_CLOSE_ON_READ_TIMEOUT) || ((SOCKERRNO != SOCK_EWOULDBLOCK) && (SOCKERRNO != SOCK_EINTR)); if (should_close) { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "%s read error: %s", tty->IPDeviceName, strerror(SOCKERRNO)); closeConnection(pasynUser,tty,"Read error"); status = asynError; } else { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "%s timeout: %s", tty->IPDeviceName, strerror(SOCKERRNO)); status = asynTimeout; } } /* If recv() returns 0 on a SOCK_STREAM (TCP) socket, the connection has closed */ if ((thisRead == 0) && (tty->socketType == SOCK_STREAM)) { epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize, "%s connection closed", tty->IPDeviceName); closeConnection(pasynUser,tty,"Read from broken connection"); reason |= ASYN_EOM_END; } if (thisRead < 0) thisRead = 0; *nbytesTransfered = thisRead; /* If there is room add a null byte */ if (thisRead < (int) maxchars) data[thisRead] = 0; else reason |= ASYN_EOM_CNT; if (gotEom) *gotEom = reason; return status; }
/** This thread controls acquisition, reads image files to get the image data, * and does the callbacks to send it to higher layers */ void hdf5Driver::hdf5Task (void) { const char *functionName = "hdf5Task"; int status = asynSuccess; epicsTimeStamp startTime, endTime; int imageMode, currentFrame, colorMode; double acquirePeriod, elapsedTime, delay; this->lock(); for(;;) { int acquire; getIntegerParam(ADAcquire, &acquire); if (!acquire) { this->unlock(); // Wait for semaphore unlocked asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: waiting for acquire to start\n", driverName, functionName); status = epicsEventWait(this->mStartEventId); this->lock(); acquire = 1; setStringParam(ADStatusMessage, "Acquiring data"); setIntegerParam(ADNumImagesCounter, 0); } // Are there datasets loaded? if(!mDatasetsCount) { setStringParam(ADStatusMessage, "No datasets loaded"); goto error; } // Get acquisition parameters epicsTimeGetCurrent(&startTime); getIntegerParam(ADImageMode, &imageMode); getDoubleParam(ADAcquirePeriod, &acquirePeriod); getIntegerParam(HDF5CurrentFrame, ¤tFrame); setIntegerParam(ADStatus, ADStatusAcquire); callParamCallbacks(); // Get information to allocate NDArray size_t dims[2]; NDDataType_t dataType; if(getFrameInfo(currentFrame, dims, &dataType)) { setStringParam(ADStatusMessage, "Failed to get frame info"); goto error; } // Allocate NDArray NDArray *pImage; if(!(pImage = pNDArrayPool->alloc(2, dims, dataType, 0, NULL))) { setStringParam(ADStatusMessage, "Failed to allocate frame"); goto error; } // Copy data into NDArray if(getFrameData(currentFrame, pImage->pData)) { setStringParam(ADStatusMessage, "Failed to read frame data"); goto error; } // Set ColorMode colorMode = NDColorModeMono; pImage->pAttributeList->add("ColorMode", "Color mode", NDAttrInt32, &colorMode); // Call plugins callbacks int arrayCallbacks; getIntegerParam(NDArrayCallbacks, &arrayCallbacks); if (arrayCallbacks) { this->unlock(); asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: calling imageData callback\n", driverName, functionName); doCallbacksGenericPointer(pImage, NDArrayData, 0); this->lock(); } pImage->release(); // Get the current parameters int lastFrame, imageCounter, numImages, numImagesCounter; getIntegerParam(HDF5LastFrame, &lastFrame); getIntegerParam(NDArrayCounter, &imageCounter); getIntegerParam(ADNumImages, &numImages); getIntegerParam(ADNumImagesCounter, &numImagesCounter); setIntegerParam(NDArrayCounter, ++imageCounter); setIntegerParam(ADNumImagesCounter, ++numImagesCounter); setIntegerParam(HDF5CurrentFrame, ++currentFrame); // Put the frame number and time stamp into the buffer pImage->uniqueId = imageCounter; pImage->timeStamp = startTime.secPastEpoch + startTime.nsec / 1.e9; updateTimeStamp(&pImage->epicsTS); // Prepare loop if necessary int loop; getIntegerParam(HDF5Loop, &loop); if (loop && currentFrame > lastFrame) { getIntegerParam(HDF5FirstFrame, ¤tFrame); setIntegerParam(HDF5CurrentFrame, currentFrame); } // See if acquisition is done if (imageMode == ADImageSingle || currentFrame > lastFrame || (imageMode == ADImageMultiple && numImagesCounter >= numImages)) { // First do callback on ADStatus setStringParam(ADStatusMessage, "Waiting for acquisition"); setIntegerParam(ADStatus, ADStatusIdle); acquire = 0; setIntegerParam(ADAcquire, acquire); asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: acquisition completed\n", driverName, functionName); } callParamCallbacks(); // Delay next acquisition and check if received STOP signal if(acquire) { epicsTimeGetCurrent(&endTime); elapsedTime = epicsTimeDiffInSeconds(&endTime, &startTime); delay = acquirePeriod - elapsedTime; asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: delay=%f\n", driverName, functionName, delay); if(delay > 0.0) { // Set the status to waiting to indicate we are in the delay setIntegerParam(ADStatus, ADStatusWaiting); callParamCallbacks(); this->unlock(); status = epicsEventWaitWithTimeout(mStopEventId, delay); this->lock(); if (status == epicsEventWaitOK) { acquire = 0; if (imageMode == ADImageContinuous) setIntegerParam(ADStatus, ADStatusIdle); else setIntegerParam(ADStatus, ADStatusAborted); callParamCallbacks(); } } } continue; error: setIntegerParam(ADAcquire, 0); setIntegerParam(ADStatus, ADStatusError); callParamCallbacks(); continue; } }
/** This thread controls handling of slow events - erase, acquire, change mode */ void mar345::mar345Task() { int status = asynSuccess; int numImages, numImagesCounter; int imageMode; int acquire; double acquirePeriod; double elapsedTime, delayTime; const char *functionName = "mar345Task"; this->lock(); /* Loop forever */ while (1) { setStringParam(ADStatusMessage, "Waiting for event"); callParamCallbacks(); /* Release the lock while we wait for an event that says acquire has started, then lock again */ this->unlock(); asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: waiting for start event\n", driverName, functionName); status = epicsEventWait(this->startEventId); this->lock(); switch(this->mode) { case mar345ModeErase: this->erase(); this->mode = mar345ModeIdle; break; case mar345ModeAcquire: getIntegerParam(ADImageMode, &imageMode); getIntegerParam(ADNumImages, &numImages); if (numImages < 1) numImages = 1; if (imageMode == ADImageSingle) numImages=1; for (numImagesCounter=0; numImagesCounter<numImages || (imageMode == ADImageContinuous); numImagesCounter++) { if (epicsEventTryWait(this->abortEventId) == epicsEventWaitOK) break; setIntegerParam(ADNumImagesCounter, numImagesCounter); callParamCallbacks(); status = acquireFrame(); if (status) break; /* We get out of the loop in single shot mode or if acquire was set to 0 by client */ if (imageMode == ADImageSingle) setIntegerParam(ADAcquire, 0); getIntegerParam(ADAcquire, &acquire); if (!acquire) break; /* We are in continuous or multiple mode. * Sleep until the acquire period expires or acquire is set to stop */ epicsTimeGetCurrent(&this->acqEndTime); elapsedTime = epicsTimeDiffInSeconds(&this->acqEndTime, &this->acqStartTime); getDoubleParam(ADAcquirePeriod, &acquirePeriod); delayTime = acquirePeriod - elapsedTime; if (delayTime > 0.) { setIntegerParam(ADStatus, mar345StatusWaiting); callParamCallbacks(); this->unlock(); status = epicsEventWaitWithTimeout(this->abortEventId, delayTime); this->lock(); if (status == epicsEventWaitOK) break; } } this->mode = mar345ModeIdle; setIntegerParam(ADAcquire, 0); setIntegerParam(ADStatus, mar345StatusIdle); break; case mar345ModeChange: this->changeMode(); this->mode = mar345ModeIdle; break; default: break; } /* Call the callbacks to update any changes */ callParamCallbacks(); } }
asynStatus mar345::acquireFrame() { asynStatus status=asynSuccess; epicsTimeStamp startTime, currentTime; int eraseMode; epicsEventWaitStatus waitStatus; int imageCounter; int arrayCallbacks; double acquireTime; double timeRemaining; int size, res; int shutterMode, useShutter; char tempFileName[MAX_FILENAME_LEN]; char fullFileName[MAX_FILENAME_LEN]; //const char *functionName = "acquireframe"; /* Get current values of some parameters */ getDoubleParam(ADAcquireTime, &acquireTime); getIntegerParam(ADShutterMode, &shutterMode); getIntegerParam(mar345Size, &size); getIntegerParam(mar345Res, &res); getIntegerParam(NDArrayCallbacks, &arrayCallbacks); getIntegerParam(mar345EraseMode, &eraseMode); if (shutterMode == ADShutterModeNone) useShutter=0; else useShutter=1; epicsTimeGetCurrent(&this->acqStartTime); createFileName(MAX_FILENAME_LEN, tempFileName); /* We need to append the extension */ epicsSnprintf(fullFileName, sizeof(fullFileName), "%s.mar%d", tempFileName, imageSizes[res][size]); /* Erase before exposure if set */ if (eraseMode == mar345EraseBefore) { status = this->erase(); if (status) return(status); } /* Set the the start time for the TimeRemaining counter */ epicsTimeGetCurrent(&startTime); timeRemaining = acquireTime; if (useShutter) setShutter(1); /* Wait for the exposure time using epicsEventWaitWithTimeout, * so we can abort */ epicsTimerStartDelay(this->timerId, acquireTime); setIntegerParam(ADStatus, mar345StatusExpose); callParamCallbacks(); while(1) { if (epicsEventTryWait(this->abortEventId) == epicsEventWaitOK) { status = asynError; break; } this->unlock(); waitStatus = epicsEventWaitWithTimeout(this->stopEventId, MAR345_POLL_DELAY); this->lock(); if (waitStatus == epicsEventWaitOK) { /* The acquisition was stopped before the time was complete */ epicsTimerCancel(this->timerId); break; } epicsTimeGetCurrent(¤tTime); timeRemaining = acquireTime - epicsTimeDiffInSeconds(¤tTime, &startTime); if (timeRemaining < 0.) timeRemaining = 0.; setDoubleParam(ADTimeRemaining, timeRemaining); callParamCallbacks(); } setDoubleParam(ADTimeRemaining, 0.0); if (useShutter) setShutter(0); setIntegerParam(ADStatus, mar345StatusIdle); callParamCallbacks(); // If the exposure was aborted return error if (status) return asynError; setIntegerParam(ADStatus, mar345StatusScan); callParamCallbacks(); epicsSnprintf(this->toServer, sizeof(this->toServer), "COMMAND SCAN %s", fullFileName); setStringParam(NDFullFileName, fullFileName); callParamCallbacks(); writeServer(this->toServer); status = waitForCompletion("SCAN_DATA Ended o.k.", MAR345_COMMAND_TIMEOUT); if (status) { return asynError; } getIntegerParam(NDArrayCounter, &imageCounter); imageCounter++; setIntegerParam(NDArrayCounter, imageCounter); /* Call the callbacks to update any changes */ callParamCallbacks(); /* If arrayCallbacks is set then read the file back in */ if (arrayCallbacks) { getImageData(); } /* Erase after scanning if set */ if (eraseMode == mar345EraseAfter) status = this->erase(); return status; }