static void interruptCallbackInput(void *drvPvt, asynUser *pasynUser, epicsFloat64 value) { devPvt *pPvt = (devPvt *)drvPvt; dbCommon *pr = pPvt->pr; ringBufferElement *rp; asynPrint(pPvt->pasynUser, ASYN_TRACEIO_DEVICE, "%s devAsynFloat64::interruptCallbackInput new value=%f\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); rp = &pPvt->ringBuffer[pPvt->ringHead]; rp->value = value; rp->time = pasynUser->timestamp; rp->status = pasynUser->auxStatus; pPvt->ringHead = (pPvt->ringHead==pPvt->ringSize) ? 0 : pPvt->ringHead+1; if (pPvt->ringHead == pPvt->ringTail) { /* 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 */ pPvt->ringTail = (pPvt->ringTail==pPvt->ringSize) ? 0 : pPvt->ringTail+1; 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); }
epicsShareFunc int epicsShareAPI epicsMessageQueuePending(epicsMessageQueueId pmsg) { char *myInPtr, *myOutPtr; int nmsg; epicsMutexLock(pmsg->mutex); myInPtr = (char *)pmsg->inPtr; myOutPtr = (char *)pmsg->outPtr; if (pmsg->full) nmsg = pmsg->capacity; else if (myInPtr >= myOutPtr) nmsg = (myInPtr - myOutPtr) / pmsg->slotSize; else nmsg = pmsg->capacity - (myOutPtr - myInPtr) / pmsg->slotSize; epicsMutexUnlock(pmsg->mutex); return nmsg; }
static void drvMK80S_timeoutCallback(asynUser* pasynMK80SUser) { kuDebug (kuTRACE, "[drvMK80S_timeoutCallback] timeout \n"); asynMK80SUserData* pasynMK80SUserData = (asynMK80SUserData*) pasynMK80SUser->userPvt; drvMK80SConfig* pdrvMK80SConfig = (drvMK80SConfig*) pasynMK80SUserData->pdrvMK80SConfig; pdrvMK80SConfig->status |= MK80SSTATUS_TIMEOUT_MASK; epicsMutexLock(pdrvMK80SConfig->lock); pdrvMK80SConfig->cbCount =0; pdrvMK80SConfig->timeoutCount++; epicsMutexUnlock(pdrvMK80SConfig->lock); scanIoRequest(pdrvMK80SConfig->ioScanPvt); return; }
LOCAL long devSiTPG262Read_gst_str(drvTPG262Config* pdrvTPG262Config, int gauge_num, char* gst_str) { TPG262_read* pTPG262_read = (TPG262_read*)pdrvTPG262Config->pTPG262_read; epicsMutexLock(pdrvTPG262Config->lock); switch(gauge_num){ case 0: strcpy(gst_str, pTPG262_read->gst_str0); break; case 1: strcpy(gst_str, pTPG262_read->gst_str1); break; default: gst_str[0] = NULL; } epicsMutexUnlock(pdrvTPG262Config->lock); return 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); }
static void interruptCallbackAverage(void *drvPvt, asynUser *pasynUser, epicsInt32 value) { devInt32Pvt *pPvt = (devInt32Pvt *)drvPvt; aiRecord *pai = (aiRecord *)pPvt->pr; if (pPvt->mask) { value &= pPvt->mask; if (pPvt->bipolar && (value & pPvt->signBit)) value |= ~pPvt->mask; } asynPrint(pPvt->pasynUser, ASYN_TRACEIO_DEVICE, "%s devAsynInt32::interruptCallbackAverage new value=%d\n", pai->name, value); epicsMutexLock(pPvt->ringBufferLock); pPvt->numAverage++; pPvt->sum += (double)value; pPvt->result.status |= pasynUser->auxStatus; epicsMutexUnlock(pPvt->ringBufferLock); }
static long update_params(epidRecord *pepid) { epidFastPvt *pPvt = (epidFastPvt *)pepid->dpvt; epicsMutexLock(pPvt->mutexId); /* If the user has changed the value of dt, requested time per point, * then update numAverage */ if (pepid->dt != pPvt->timePerPointActual) { pPvt->timePerPointRequested = pepid->dt; computeNumAverage(pPvt); } /* Copy values from private structure to record */ pepid->cval = pPvt->actual; pepid->err = pPvt->error; pepid->oval = pPvt->output; pepid->p = pPvt->P; pepid->i = pPvt->I; pepid->d = pPvt->D; pepid->dt = pPvt->timePerPointActual; /* Copy values from record to private structure */ pPvt->feedbackOn = pepid->fbon; pPvt->highLimit = pepid->drvh; pPvt->lowLimit = pepid->drvl; pPvt->KP = pepid->kp; pPvt->KI = pepid->ki; pPvt->KD = pepid->kd; pPvt->setPoint = pepid->val; epicsMutexUnlock(pPvt->mutexId); asynPrint(pPvt->pcallbackDataAsynUser, ASYN_TRACEIO_DEVICE, "devEpidFast::update_params, record=%s\n " " feedback state %d, previous feedback state %d\n" " cval=%f, err=%f, oval=%f,\n" " P=%f, I=%f, D=%f, dt=%f\n", pepid->name, pPvt->feedbackOn, pPvt->prevFeedbackOn, pepid->cval, pepid->err, pepid->oval, pepid->p, pepid->i, pepid->d, pepid->dt); pepid->udf=0; return(0); }
LOCAL long devAiTPG262Read_prs(drvTPG262Config* pdrvTPG262Config, int gauge_num,double* prs) { TPG262_read* pTPG262_read = (TPG262_read*)pdrvTPG262Config->pTPG262_read; epicsMutexLock(pdrvTPG262Config->lock); switch(gauge_num) { case 0: *prs = pTPG262_read->prs0; break; case 1: *prs = pTPG262_read->prs1; break; default: *prs = -1.; } epicsMutexUnlock(pdrvTPG262Config->lock); return 0; }
/** Finds an attribute by name; the search is case-insensitive. * \param[in] pName The name of the attribute to be found. * \return Returns a pointer to the attribute if found, NULL if not found. */ NDAttribute* NDAttributeList::find(const char *pName) { NDAttribute *pAttribute; NDAttributeListNode *pListNode; //const char *functionName = "NDAttributeList::find"; epicsMutexLock(this->lock); pListNode = (NDAttributeListNode *)ellFirst(&this->list); while (pListNode) { pAttribute = pListNode->pNDAttribute; if (epicsStrCaseCmp(pAttribute->pName, pName) == 0) goto done; pListNode = (NDAttributeListNode *)ellNext(&pListNode->node); } pAttribute = NULL; done: epicsMutexUnlock(this->lock); return(pAttribute); }
static int motorAxisHome( AXIS_HDL pAxis, double min_velocity, double max_velocity, double acceleration, int forwards ) { int status = MOTOR_AXIS_ERROR; if (pAxis == NULL) status = MOTOR_AXIS_ERROR; else { if (epicsMutexLock( pAxis->axisMutex ) == epicsMutexLockOK) { status = motorAxisVelocity( pAxis, (forwards? max_velocity: -max_velocity), acceleration ); pAxis->homing = 1; motorParam->setInteger( pAxis->params, motorAxisDone, 0 ); motorParam->callCallback( pAxis->params ); epicsMutexUnlock( pAxis->axisMutex ); pAxis->print( pAxis->logParam, TRACE_FLOW, "Set card %d, axis %d to home %s, min vel=%f, max_vel=%f, accel=%f", pAxis->card, pAxis->axis, (forwards?"FORWARDS":"REVERSE"), min_velocity, max_velocity, acceleration ); } } return status; }
static int motorAxisVelocityMove( AXIS_HDL pAxis, double min_velocity, double velocity, double acceleration ) { int status = MOTOR_AXIS_ERROR; if (pAxis == NULL) status = MOTOR_AXIS_ERROR; else { if (epicsMutexLock( pAxis->axisMutex ) == epicsMutexLockOK) { status = motorAxisVelocity( pAxis, velocity, acceleration ); motorParam->setInteger( pAxis->params, motorAxisDone, 0 ); motorParam->callCallback( pAxis->params ); epicsMutexUnlock( pAxis->axisMutex ); pAxis->print( pAxis->logParam, TRACE_FLOW, "Set card %d, axis %d move with velocity of %f, accel=%f", pAxis->card, pAxis->axis, velocity, acceleration ); } } return status; }
LOCAL long devBiGP307_read_bi_synchronous(biRecord *precord) { devGP307dpvt *pdevGP307dpvt = (devGP307dpvt*)precord->dpvt; drvGP307Config *pdrvGP307Config = (drvGP307Config*)pdevGP307dpvt->pdrvGP307Config; GP307_read *pGP307_read = (GP307_read*)pdrvGP307Config->pGP307_read; switch(pdevGP307dpvt->param){ case GP307DEVPARAM_STATUSCG0: epicsMutexLock(pdrvGP307Config->lock); precord->rval = (pGP307_read->status & GP307STATUS_CG0VALID_MASK)?1:0; epicsMutexUnlock(pdrvGP307Config->lock); break; case GP307DEVPARAM_STATUSCG1: epicsMutexLock(pdrvGP307Config->lock); precord->rval = (pGP307_read->status & GP307STATUS_CG1VALID_MASK)?1:0; epicsMutexUnlock(pdrvGP307Config->lock); break; case GP307DEVPARAM_STATUSIG: epicsMutexLock(pdrvGP307Config->lock); precord->rval = (pGP307_read->status & GP307STATUS_IGVALID_MASK)?1:0; epicsMutexUnlock(pdrvGP307Config->lock); break; case GP307DEVPARAM_STATUSTIMEOUT: epicsMutexLock(pdrvGP307Config->lock); precord->rval = (pGP307_read->status & GP307STATUS_TIMEOUT_MASK)?1:0; epicsMutexUnlock(pdrvGP307Config->lock); break; case GP307DEVPARAM_STATUSONOFFIG0: epicsMutexLock(pdrvGP307Config->lock); precord->rval = (pGP307_read->status & GP307STATUS_IG0ONOFF_MASK)?1:0; epicsMutexUnlock(pdrvGP307Config->lock); break; case GP307DEVPARAM_STATUSONOFFIG1: epicsMutexLock(pdrvGP307Config->lock); precord->rval = (pGP307_read->status & GP307STATUS_IG1ONOFF_MASK)?1:0; epicsMutexUnlock(pdrvGP307Config->lock); break; default: precord->pact = TRUE; precord->udf = TRUE; return 0; } precord->val = precord->rval; precord->udf = FALSE; return 2; /* don't do any conversion */ }
/* This is the function that is called back from the driver when a new readback * value is obtained */ static void dataCallback(void *drvPvt, asynUser *pasynUser, double readBack) { epidFastPvt *pPvt = (epidFastPvt *)drvPvt; epicsMutexLock(pPvt->mutexId); /* No need to average if collecting every point */ if (pPvt->numAverage == 1) { do_PID(pPvt, readBack); goto done; } pPvt->averageStore += readBack; if (++pPvt->accumulated < pPvt->numAverage) goto done; /* We have now collected the desired number of points to average */ pPvt->averageStore /= pPvt->accumulated; do_PID(pPvt, pPvt->averageStore); pPvt->averageStore = 0.; pPvt->accumulated = 0; done: epicsMutexUnlock(pPvt->mutexId); }
epicsShareFunc boolean seqQueueGetF(QUEUE q, seqQueueFunc *get, void *arg) { if (q->wr == q->rd) { if (!q->overflow) { return TRUE; } epicsMutexLock(q->mutex); get(arg, q->buffer + q->rd * q->elemSize, q->elemSize); /* check again, a put might have intervened */ if (q->wr == q->rd && q->overflow) q->overflow = FALSE; else q->rd = (q->rd + 1) % q->numElems; epicsMutexUnlock(q->mutex); } else { get(arg, q->buffer + q->rd * q->elemSize, q->elemSize); q->rd = (q->rd + 1) % q->numElems; } return FALSE; }
/* Create a PLC entry: * name : identifier * ip_address: DNS name or dot-notation */ eip_bool drvEtherIP_define_PLC(const char *PLC_name, const char *ip_addr, int slot) { PLC *plc; epicsMutexLock(drvEtherIP_private.lock); plc = get_PLC(PLC_name, true); if (plc) { if (plc->ip_addr) { EIP_printf(1, "Redefining IP address of PLC %s?\n", PLC_name); free(plc->ip_addr); } plc->ip_addr = EIP_strdup(ip_addr); plc->slot = slot; } epicsMutexUnlock(drvEtherIP_private.lock); return plc && plc->ip_addr; }
/** Reports on the properties of the attribute list. * \param[in] details Level of report details desired; if >10 calls NDAttribute::report() for each attribute. */ int NDAttributeList::report(int details) { NDAttribute *pAttribute; NDAttributeListNode *pListNode; epicsMutexLock(this->lock); printf("\n"); printf("NDAttributeList: address=%p:\n", this); printf(" number of attributes=%d\n", this->count()); if (details > 10) { pListNode = (NDAttributeListNode *) ellFirst(&this->list); while (pListNode) { pAttribute = (NDAttribute *)pListNode->pNDAttribute; pAttribute->report(details); pListNode = (NDAttributeListNode *) ellNext(&pListNode->node); } } epicsMutexUnlock(this->lock); return ND_SUCCESS; }
/** Base method for reading a file * Creates the file name with NDPluginBase::createFileName, then calls the pure virtual functions openFile, * readFile and closeFile in the derived class. Does callbacks with the NDArray that was read in. */ asynStatus NDPluginFile::readFileBase(void) { asynStatus status = asynSuccess; char fullFileName[MAX_FILENAME_LEN]; int dataType=0; NDArray *pArray=NULL; static const char* functionName = "readFileBase"; status = (asynStatus)createFileName(MAX_FILENAME_LEN, fullFileName); if (status) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s error creating full file name, fullFileName=%s, status=%d\n", driverName, functionName, fullFileName, status); return(status); } /* Call the readFile method in the derived class */ /* Do this with the main lock released since it is slow */ this->unlock(); epicsMutexLock(this->fileMutexId); status = this->openFile(fullFileName, NDFileModeRead, pArray); status = this->readFile(&pArray); status = this->closeFile(); epicsMutexUnlock(this->fileMutexId); this->lock(); /* If we got an error then return */ if (status) return(status); /* Update the new values of dimensions and the array data */ setIntegerParam(NDDataType, dataType); /* Call any registered clients */ doCallbacksGenericPointer(pArray, NDArrayData, 0); /* Set the last array to be this one */ this->pArrays[0]->release(); this->pArrays[0] = pArray; return(status); }
/** Copies all attributes from one attribute list to another. * It is efficient so that if the attribute already exists in the output * list it just copies the properties, and memory allocation is minimized. * The attributes are added to any existing attributes already present in the output list. * \param[out] pListOut A pointer to the output attribute list to copy to. */ int NDAttributeList::copy(NDAttributeList *pListOut) { NDAttribute *pAttrIn, *pAttrOut, *pFound; NDAttributeListNode *pListNode; //const char *functionName = "NDAttributeList::copy"; epicsMutexLock(this->lock); pListNode = (NDAttributeListNode *)ellFirst(&this->list); while (pListNode) { pAttrIn = pListNode->pNDAttribute; /* See if there is already an attribute of this name in the output list */ pFound = pListOut->find(pAttrIn->pName); /* The copy function will copy the properties, and will create the attribute if pFound is NULL */ pAttrOut = pAttrIn->copy(pFound); /* If pFound is NULL, then a copy created a new attribute, need to add it to the list */ if (!pFound) pListOut->add(pAttrOut); pListNode = (NDAttributeListNode *)ellNext(&pListNode->node); } epicsMutexUnlock(this->lock); return(ND_SUCCESS); }
static int getCallbackValue(devPvt *pPvt) { int ret = 0; epicsMutexLock(pPvt->ringBufferLock); if (pPvt->ringTail != pPvt->ringHead) { if (pPvt->ringBufferOverflows > 0) { asynPrint(pPvt->pasynUser, ASYN_TRACE_WARNING, "%s devAsynFloat64 getCallbackValue error, %d ring buffer overflows\n", pPvt->pr->name, pPvt->ringBufferOverflows); pPvt->ringBufferOverflows = 0; } pPvt->result = pPvt->ringBuffer[pPvt->ringTail]; pPvt->ringTail = (pPvt->ringTail==pPvt->ringSize) ? 0 : pPvt->ringTail+1; asynPrint(pPvt->pasynUser, ASYN_TRACEIO_DEVICE, "%s devAsynFloat64::getCallbackValue from ringBuffer value=%f\n", pPvt->pr->name,pPvt->result.value); ret = 1; } epicsMutexUnlock(pPvt->ringBufferLock); return ret; }
static void devSNMPScanThread(void) { ELLLIST *pdevSNMPList = &devSNMPList; devSNMPPvt *pSNMPPvt; while(!pdevSNMPList->count) { epicsThreadSleep(0.5); } while(TRUE) { pSNMPPvt = (devSNMPPvt*) ellFirst(pdevSNMPList); do { epicsMutexLock(pSNMPPvt->mutexId); //critical section epicsMutexUnlock(pSNMPPvt->mutexId); scanIoRequest(pSNMPPvt->ioScanPvt); } while( (pSNMPPvt = (devSNMPPvt*) ellNext(&pSNMPPvt->devSNMPNode)) ); epicsThreadSleep(0.1); } }
/* After the PLC is defined with drvEtherIP_define_PLC, * tags can be added */ TagInfo *drvEtherIP_add_tag(PLC *plc, double period, const char *string_tag, size_t elements) { ScanList *list; TagInfo *info; epicsMutexLock(plc->lock); if (find_PLC_tag(plc, string_tag, &list, &info)) { /* check if period is OK */ if (list->period > period) { /* current scanlist is too slow */ remove_ScanList_TagInfo(list, info); list = get_PLC_ScanList(plc, period, true); if (!list) { epicsMutexUnlock(plc->lock); EIP_printf(2, "drvEtherIP: cannot create list at %g secs" "for tag '%s'\n", period, string_tag); return 0; } add_ScanList_TagInfo(list, info); } if (info->elements < elements) /* maximize element count */ info->elements = elements; } else { /* new tag */ list = get_PLC_ScanList(plc, period, true); if (list) info = add_ScanList_Tag(list, string_tag, elements); else { EIP_printf(2, "drvEtherIP: cannot create list at %g secs" "for tag '%s'\n", period, string_tag); info = 0; } } epicsMutexUnlock(plc->lock); return info; }
/* ------------------------------------------------------------ * TagInfo * ------------------------------------------------------------ */ static void dump_TagInfo(const TagInfo *info, int level) { char buffer[EIP_MAX_TAG_LENGTH]; printf("*** Tag '%s' @ 0x%lX:\n", info->string_tag, (unsigned long)info); if (level > 3) { printf(" scanlist : 0x%lX\n", (unsigned long)info->scanlist); EIP_copy_ParsedTag(buffer, info->tag); printf(" compiled tag : '%s', %d elements\n", buffer, (unsigned)info->elements); printf(" cip read requ./resp.: %u / %u\n", (unsigned)info->cip_r_request_size, (unsigned)info->cip_r_response_size); printf(" cip write req./resp.: %u / %u\n", (unsigned)info->cip_w_request_size, (unsigned)info->cip_w_response_size); printf(" data_lock ID : 0x%lX\n", (unsigned long) info->data_lock); } if (epicsMutexLock(info->data_lock) == epicsMutexLockOK) { if (level > 3) { printf(" data_size / valid : %u / %u\n", (unsigned)info->data_size, (unsigned)info->valid_data_size); printf(" do_write/is_writing : %s / %s\n", (info->do_write ? "yes" : "no"), (info->is_writing ? "yes" : "no")); EIP_printf(0, " data : "); } if (info->valid_data_size > 0) dump_raw_CIP_data(info->data, info->elements); else printf("-no data-\n"); epicsMutexUnlock(info->data_lock); } else printf(" (CANNOT GET DATA LOCK!)\n"); if (level > 3) printf(" transfer time : %g secs\n", info->transfer_time); }
/** Base method for opening a file * Creates the file name with NDPluginBase::createFileName, then calls the pure virtual function openFile * in the derived class. */ asynStatus NDPluginFile::openFileBase(NDFileOpenMode_t openMode, NDArray *pArray) { /* Opens a file for reading or writing */ asynStatus status = asynSuccess; char fullFileName[MAX_FILENAME_LEN]; char errorMessage[256]; const char* functionName = "openFileBase"; if (this->useAttrFilePrefix) this->attrFileNameSet(); setIntegerParam(NDFileWriteStatus, NDFileWriteOK); setStringParam(NDFileWriteMessage, ""); status = (asynStatus)createFileName(MAX_FILENAME_LEN, fullFileName); if (status) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s error creating full file name, fullFileName=%s, status=%d\n", driverName, functionName, fullFileName, status); setIntegerParam(NDFileWriteStatus, NDFileWriteError); setStringParam(NDFileWriteMessage, "Error creating full file name"); return(status); } setStringParam(NDFullFileName, fullFileName); /* Call the openFile method in the derived class */ epicsMutexLock(this->fileMutexId); status = this->openFile(fullFileName, openMode, pArray); if (status) { epicsSnprintf(errorMessage, sizeof(errorMessage)-1, "Error opening file %s, status=%d", fullFileName, status); asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s %s\n", driverName, functionName, errorMessage); setIntegerParam(NDFileWriteStatus, NDFileWriteError); setStringParam(NDFileWriteMessage, errorMessage); } epicsMutexUnlock(this->fileMutexId); return(status); }
static int motorAxisMove( AXIS_HDL pAxis, double position, int relative, double min_velocity, double max_velocity, double acceleration ) { if (pAxis == NULL) return MOTOR_AXIS_ERROR; else { if (relative) position += pAxis->endpoint.axis[0].p + pAxis->enc_offset; /* Check to see if in hard limits */ if ((pAxis->nextpoint.axis[0].p >= pAxis->hiHardLimit && position > pAxis->nextpoint.axis[0].p) || (pAxis->nextpoint.axis[0].p <= pAxis->lowHardLimit && position < pAxis->nextpoint.axis[0].p) ) return MOTOR_AXIS_ERROR; else if (epicsMutexLock( pAxis->axisMutex ) == epicsMutexLockOK) { route_pars_t pars; if (pAxis->pDrv->movesDeferred == 0) { /*Normal move.*/ pAxis->endpoint.axis[0].p = position - pAxis->enc_offset; pAxis->endpoint.axis[0].v = 0.0; } else { /*Deferred moves.*/ pAxis->deferred_position = position; pAxis->deferred_move = 1; pAxis->deferred_relative = relative; } routeGetParams( pAxis->route, &pars ); if (max_velocity != 0) pars.axis[0].Vmax = fabs(max_velocity); if (acceleration != 0) pars.axis[0].Amax = fabs(acceleration); routeSetParams( pAxis->route, &pars ); motorParam->setInteger( pAxis->params, motorAxisDone, 0 ); motorParam->callCallback( pAxis->params ); epicsMutexUnlock( pAxis->axisMutex ); pAxis->print( pAxis->logParam, TRACE_FLOW, "Set card %d, axis %d move to %f, min vel=%f, max_vel=%f, accel=%f", pAxis->card, pAxis->axis, position, min_velocity, max_velocity, acceleration ); } } return MOTOR_AXIS_OK; }
static int motorAxisMove(AXIS_HDL pAxis, double position, int relative, double min_velocity, double max_velocity, double acceleration) { int status; char buff[100]; char *moveCommand; if (pAxis == NULL) return MOTOR_AXIS_ERROR; PRINT(pAxis->logParam, FLOW, "Set card %d, axis %d move to %f, min vel=%f, max_vel=%f, accel=%f\n", pAxis->card, pAxis->axis, position, min_velocity, max_velocity, acceleration); if (relative) { moveCommand = "PR"; } else { moveCommand = "PA"; } sprintf(buff, "%dAC%.*f;%dVA%.*f;%d%s%.*f;", pAxis->axis+1, pAxis->maxDigits, acceleration * pAxis->stepSize, pAxis->axis+1, pAxis->maxDigits, max_velocity * pAxis->stepSize, pAxis->axis+1, moveCommand, pAxis->maxDigits, position * pAxis->stepSize); status = sendOnly(pAxis->pController, buff); if (status) return MOTOR_AXIS_ERROR; if (epicsMutexLock(pAxis->mutexId) == epicsMutexLockOK) { /* Insure that the motor record's next status update sees motorAxisDone = False. */ motorParam->setInteger(pAxis->params, motorAxisDone, 0); motorParam->callCallback(pAxis->params); epicsMutexUnlock(pAxis->mutexId); } /* Send a signal to the poller task which will make it do a poll, and switch to the moving poll rate */ epicsEventSignal(pAxis->pController->pollEventId); return MOTOR_AXIS_OK; }
void drvEtherIP_add_callback (PLC *plc, TagInfo *info, EIPCallback callback, void *arg) { TagCallback *cb; epicsMutexLock(plc->lock); for (cb = DLL_first(TagCallback, &info->callbacks); cb; cb = DLL_next(TagCallback, cb)) { if (cb->callback == callback && cb->arg == arg) { epicsMutexUnlock(plc->lock); return; } } /* Add new one */ if (!(cb = (TagCallback *) malloc(sizeof (TagCallback)))) return; cb->callback = callback; cb->arg = arg; DLL_append(&info->callbacks, cb); epicsMutexUnlock(plc->lock); }
static int getCallbackValue(devPvt *pPvt) { int ret = 0; static const char *functionName="getCallbackValue"; epicsMutexLock(pPvt->devPvtLock); if (pPvt->ringTail != pPvt->ringHead) { if (pPvt->ringBufferOverflows > 0) { asynPrint(pPvt->pasynUser, ASYN_TRACE_WARNING, "%s %s::%s warning, %d ring buffer overflows\n", pPvt->pr->name, driverName, functionName,pPvt->ringBufferOverflows); pPvt->ringBufferOverflows = 0; } pPvt->result = pPvt->ringBuffer[pPvt->ringTail]; pPvt->ringTail = (pPvt->ringTail==pPvt->ringSize) ? 0 : pPvt->ringTail+1; asynPrint(pPvt->pasynUser, ASYN_TRACEIO_DEVICE, "%s %s::%s from ringBuffer value=%f\n", pPvt->pr->name, driverName, functionName, pPvt->result.value); ret = 1; } epicsMutexUnlock(pPvt->devPvtLock); return ret; }
static int motorAxisInit(void) { int controller, axis; for (controller = 0; controller < numMM4000Controllers; controller++) { AXIS_HDL pAxis; for (axis = 0; axis < pMM4000Controller[controller].numAxes; axis++) { pAxis = &pMM4000Controller[controller].pAxis[axis]; if (!pAxis->mutexId) break; epicsMutexLock(pAxis->mutexId); /*Set GAIN_SUPPORT on so that at least, CNEN functions. */ motorParam->setInteger(pAxis->params, motorAxisHasClosedLoop, 1); motorParam->callCallback(pAxis->params); epicsMutexUnlock(pAxis->mutexId); } } return(MOTOR_AXIS_OK); }
/* * get the access rights: * note that even though there is separate read and write access, the rights * as of R3.14.1 are actually [ NONE, READ, and READ/WRITE]. If this changes, * things could get interesting. */ static void getAccessRights( struct access_rights_handler_args args) { Channel *chan = ca_puser(args.chid); Connector *conp; int readAccess, writeAccess; readAccess = ca_read_access(chan->chan_id); writeAccess = ca_write_access(chan->chan_id); chan->writeAccess = writeAccess?1:0; chan->readAccess = readAccess?1:0; DEBUGP printf("Channel %s read %d write %d\n", chan->chan_name, readAccess, writeAccess); /* * user now allowed to write to this PV */ epicsMutexLock( processFlag); for( conp=chan->first_connector; conp; conp=conp->next_chan) if( conp->newAccess) (*conp->newAccess)(conp); epicsMutexUnlock( processFlag); }
static long processAiAverage(aiRecord *pr) { devInt32Pvt *pPvt = (devInt32Pvt *)pr->dpvt; double rval; epicsMutexLock(pPvt->mutexId); if (pPvt->numAverage == 0) { recGblSetSevr(pr, UDF_ALARM, INVALID_ALARM); pr->udf = 1; epicsMutexUnlock(pPvt->mutexId); return -2; } rval = pPvt->sum/pPvt->numAverage; /*round result*/ rval += (pPvt->sum>0.0) ? 0.5 : -0.5; pr->rval = (epicsInt32) rval; pPvt->numAverage = 0; pPvt->sum = 0.; epicsMutexUnlock(pPvt->mutexId); asynPrint(pPvt->pasynUser, ASYN_TRACEIO_DEVICE, "%s devAsynInt32::processAiInt32Average rval=%d\n",pr->name, pr->rval); pr->udf = 0; return 0; }