Exemple #1
0
/** Reads the values of all the modules parameters, sets them in the parameter library**/
asynStatus mythen::getSettings()
{
    int aux;
    epicsFloat32 faux;
    long long laux;
    epicsFloat64 DetTime;

    static const char *functionName = "getSettings";

    if (acquiring_) {
        strcpy(outString_,"Called during Acquire");
        inString_[0] = 0;
        goto error;
    }

    strcpy(outString_, "-get flatfieldcorrection");
    writeReadMeter();
    aux = stringToInt32(this->inString_);
    if (aux!=0 && aux!=1) goto error;
    setIntegerParam(SDUseFlatField, aux);


    strcpy(outString_, "-get badchannelinterpolation");
    writeReadMeter();
    aux = stringToInt32(this->inString_);
    if (aux!=0 && aux!=1) goto error;
    setIntegerParam(SDUseBadChanIntrpl, aux);

    strcpy(outString_, "-get ratecorrection");
    writeReadMeter();
    aux = stringToInt32(this->inString_);
    if (aux!=0 && aux!=1) goto error;
    setIntegerParam(SDUseCountRate, aux);

    strcpy(outString_, "-get nbits");
    writeReadMeter();
    aux = stringToInt32(this->inString_);
    if (aux < 0) goto error;
    nbits_ = aux;
    chanperline_ = 32/aux; 
    setIntegerParam(SDBitDepth, aux);

    strcpy(outString_, "-get time");
    writeReadMeter();
    aux = stringToInt32(this->inString_);
    if (aux >= 0) DetTime = (aux * (1E-7));
    else goto error;
    setDoubleParam(ADAcquireTime,DetTime);

    

    strcpy(outString_, "-get frames");
    writeReadMeter();
    aux = stringToInt32(this->inString_);
    if (aux >= 0) setIntegerParam(SDNumFrames, aux);

    strcpy(outString_, "-get tau");
    writeReadMeter();
    faux = stringToFloat32(this->inString_);
    if (faux == -1 || faux > 0) setDoubleParam(SDTau,faux);
    else goto error;

    

    strcpy(outString_, "-get kthresh");
    writeReadMeter();
    faux = stringToFloat32(this->inString_);
    if (faux < 0) goto error;
    else setDoubleParam(SDThreshold,faux);
      
      
    //Firmware greater than 3 commands  
    if ((int)firmwareVersion_[1]%48 >=3) {
      strcpy(outString_, "-get energy");
      writeReadMeter();
      faux = stringToFloat32(this->inString_);
      if (faux < 0) goto error;
      else setDoubleParam(SDEnergy,faux);
      
      strcpy(outString_, "-get delafter");
      writeReadMeter();
      laux = stringToInt64(this->inString_);
      if (laux >= 0) DetTime = (laux * (1E-7));
      else goto error;
      setDoubleParam(SDDelayTime,DetTime);
      
      
      /* Get trigger modes */
      strcpy(outString_, "-get conttrig");
      writeReadMeter();
      aux = stringToInt32(this->inString_);
      if (aux < 0) goto error;
      if (aux == 1) 
          setIntegerParam(SDTrigger, 2);
      else {
        strcpy(outString_, "-get trig");
        writeReadMeter();
        aux = stringToInt32(this->inString_);
        if (aux < 0) goto error;
        if (aux == 1)
          setIntegerParam(SDTrigger, 1);
        else
          setIntegerParam(SDTrigger, 0);
      }
    }

    callParamCallbacks();
    // if (prevAcquiring) setAcquire(1);

    return asynSuccess;

    error:
    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
        "%s:%s: error, outString=%s, inString=%s\n",
        driverName, functionName, outString_, inString_);
    return asynError;
}
/** Callback function that is called by the NDArray driver with new NDArray data.
  * Does image processing.
  * \param[in] pArray  The NDArray from the callback.
  */
void NDPluginProcess::processCallbacks(NDArray *pArray)
{
    /* This function does array processing.
     * It is called with the mutex already locked.  It unlocks it during long calculations when private
     * structures don't need to be protected.
     */
    size_t i;
    NDArray *pScratch=NULL;
    double  *data, newData, newFilter;
    NDArrayInfo arrayInfo;
    double  *background=NULL, *flatField=NULL, *filter=NULL;
    double  value;
    size_t  nElements;
    int     saveBackground, enableBackground, validBackground;
    int     saveFlatField,  enableFlatField,  validFlatField;
    double  scaleFlatField;
    int     enableOffsetScale, autoOffsetScale;
    double  offset, scale, minValue, maxValue;
    double  lowClip=0, highClip=0;
    int     enableLowClip, enableHighClip;
    int     resetFilter, autoResetFilter, filterCallbacks, doCallbacks=1;
    int     enableFilter, numFilter;
    int     dataType;
    int     anyProcess;
    double  oOffset, fOffset, rOffset, oScale, fScale;
    double  oc1, oc2, oc3, oc4;
    double  fc1, fc2, fc3, fc4;
    double  rc1, rc2;
    double  F1, F2, O1, O2;

    //const char* functionName = "processCallbacks";

    /* Call the base class method */
    NDPluginDriver::processCallbacks(pArray);

    /* Need to fetch all of these parameters while we still have the mutex */
    getIntegerParam(NDPluginProcessDataType,            &dataType);
    getIntegerParam(NDPluginProcessSaveBackground,      &saveBackground);
    getIntegerParam(NDPluginProcessEnableBackground,    &enableBackground);
    getIntegerParam(NDPluginProcessSaveFlatField,       &saveFlatField);
    getIntegerParam(NDPluginProcessEnableFlatField,     &enableFlatField);
    getDoubleParam (NDPluginProcessScaleFlatField,      &scaleFlatField);
    getIntegerParam(NDPluginProcessEnableOffsetScale,   &enableOffsetScale);
    getIntegerParam(NDPluginProcessAutoOffsetScale,     &autoOffsetScale);
    getIntegerParam(NDPluginProcessEnableLowClip,       &enableLowClip);
    getIntegerParam(NDPluginProcessEnableHighClip,      &enableHighClip);
    getIntegerParam(NDPluginProcessEnableFilter,        &enableFilter);
    getIntegerParam(NDPluginProcessResetFilter,         &resetFilter);
    getIntegerParam(NDPluginProcessAutoResetFilter,     &autoResetFilter);
    getIntegerParam(NDPluginProcessFilterCallbacks,     &filterCallbacks);

    if (enableOffsetScale) {
        getDoubleParam (NDPluginProcessScale,           &scale);
        getDoubleParam (NDPluginProcessOffset,          &offset);
    }
    if (enableLowClip) 
        getDoubleParam (NDPluginProcessLowClip,         &lowClip);
    if (enableHighClip) 
        getDoubleParam (NDPluginProcessHighClip,        &highClip);
    if (resetFilter) 
        setIntegerParam(NDPluginProcessResetFilter, 0);
    if (enableFilter) {
        getIntegerParam(NDPluginProcessNumFilter,       &numFilter);
        getDoubleParam (NDPluginProcessOOffset,         &oOffset);
        getDoubleParam (NDPluginProcessOScale,          &oScale);
        getDoubleParam (NDPluginProcessOC1,             &oc1);
        getDoubleParam (NDPluginProcessOC2,             &oc2);
        getDoubleParam (NDPluginProcessOC3,             &oc3);
        getDoubleParam (NDPluginProcessOC4,             &oc4);
        getDoubleParam (NDPluginProcessFOffset,         &fOffset);
        getDoubleParam (NDPluginProcessFScale,          &fScale);
        getDoubleParam (NDPluginProcessFC1,             &fc1);
        getDoubleParam (NDPluginProcessFC2,             &fc2);
        getDoubleParam (NDPluginProcessFC3,             &fc3);
        getDoubleParam (NDPluginProcessFC4,             &fc4);
        getDoubleParam (NDPluginProcessROffset,         &rOffset);
        getDoubleParam (NDPluginProcessRC1,             &rc1);
        getDoubleParam (NDPluginProcessRC2,             &rc2);
    }

    /* Release the lock now that we are only doing things that don't involve memory other thread
     * cannot access */
    this->unlock();
    /* Special case for automatic data type */
    if (dataType == -1) dataType = (int)pArray->dataType;
    
    pArray->getInfo(&arrayInfo);
    nElements = arrayInfo.nElements;

    validBackground = 0;
    if (this->pBackground && (nElements == this->nBackgroundElements)) validBackground = 1;
    setIntegerParam(NDPluginProcessValidBackground, validBackground);
    validFlatField = 0;
    if (this->pFlatField && (nElements == this->nFlatFieldElements)) validFlatField = 1;
    setIntegerParam(NDPluginProcessValidFlatField, validFlatField);

    if (validBackground && enableBackground)
        background = (double *)this->pBackground->pData;
    if (validFlatField && enableFlatField)
        flatField = (double *)this->pFlatField->pData;

    anyProcess = ((enableBackground && validBackground) ||
                  (enableFlatField && validFlatField)   ||
                   enableOffsetScale                    ||
                   autoOffsetScale                      ||
                   enableHighClip                       || 
                   enableLowClip                        ||
                   enableFilter);
    /* If no processing is to be done just convert the input array and do callbacks */
    if (!anyProcess) {
        /* Convert the array to the desired output data type */
        if (this->pArrays[0]) this->pArrays[0]->release();
        this->pNDArrayPool->convert(pArray, &this->pArrays[0], (NDDataType_t)dataType);
        goto doCallbacks;
    }
    
    /* Make a copy of the array converted to double, because we cannot modify the input array */
    this->pNDArrayPool->convert(pArray, &pScratch, NDFloat64);
    data = (double *)pScratch->pData;

    if (nElements > 0) {
        minValue = data[0];
        maxValue = data[0];
    } else {
        minValue = 0;
        maxValue = 1;
    }
    for (i=0; i<nElements; i++) {
        value = data[i];
        if (autoOffsetScale) {
            if (data[i] < minValue) minValue = data[i];
            if (data[i] > maxValue) maxValue = data[i];
        }
        if (background) value -= background[i];
        if (flatField) {
            if (flatField[i] != 0.) 
                value *= scaleFlatField / flatField[i];
            else
                value = scaleFlatField;
        }
        if (enableOffsetScale) value = (value + offset)*scale;
        if (enableHighClip && (value > highClip)) value = highClip;
        if (enableLowClip  && (value < lowClip))  value = lowClip;
        data[i] = value;
    }
    
    if (enableFilter) {
        if (this->pFilter) {
            this->pFilter->getInfo(&arrayInfo);
            if (nElements != arrayInfo.nElements) {
                this->pFilter->release();
                this->pFilter = NULL;
            }
        }
        if (!this->pFilter) {
            /* There is not a current filter array */
            /* Make a copy of the current array, converted to double type */
            this->pNDArrayPool->convert(pScratch, &this->pFilter, NDFloat64);
            resetFilter = 1;
        }
        if ((this->numFiltered >= numFilter) && autoResetFilter)
          resetFilter = 1;
        if (resetFilter) {
            filter = (double *)this->pFilter->pData;
            for (i=0; i<nElements; i++) {
                newFilter = rOffset;
                if (rc1) newFilter += rc1*filter[i];
                if (rc2) newFilter += rc2*data[i];
                filter[i] = newFilter;
            }           
            this->numFiltered = 0;
        }
        /* Do the filtering */
        if (this->numFiltered < numFilter) this->numFiltered++;
        filter = (double *)this->pFilter->pData;
        O1 = oScale * (oc1 + oc2/this->numFiltered);
        O2 = oScale * (oc3 + oc4/this->numFiltered);
        F1 = fScale * (fc1 + fc2/this->numFiltered);
        F2 = fScale * (fc3 + fc4/this->numFiltered);
        for (i=0; i<nElements; i++) {
            newData   = oOffset;
            if (O1) newData += O1 * filter[i];
            if (O2) newData += O2 * data[i];
            newFilter = fOffset;
            if (F1) newFilter += F1 * filter[i];
            if (F2) newFilter += F2 * data[i];
            data[i] = newData;
            filter[i] = newFilter;
        }
        if ((this->numFiltered != numFilter) && filterCallbacks)
          doCallbacks = 0;
    }

    if (doCallbacks) {
      /* Convert the array to the desired output data type */
      if (this->pArrays[0]) this->pArrays[0]->release();
      this->pNDArrayPool->convert(pScratch, &this->pArrays[0], (NDDataType_t)dataType);
    }

    if (autoOffsetScale && this->pArrays[0] != NULL) {
        this->pArrays[0]->getInfo(&arrayInfo);
        double maxScale = pow(2., arrayInfo.bytesPerElement*8) - 1;
        scale = maxScale /(maxValue-minValue);
        offset = -minValue;
        setDoubleParam (NDPluginProcessScale,             scale);
        setDoubleParam (NDPluginProcessOffset,            offset);
        setDoubleParam (NDPluginProcessLowClip,           0);
        setDoubleParam (NDPluginProcessHighClip,          maxScale);
        setIntegerParam(NDPluginProcessEnableOffsetScale, 1);
        setIntegerParam(NDPluginProcessEnableLowClip,     1);
        setIntegerParam(NDPluginProcessEnableHighClip,    1);
    }

    doCallbacks:    
    if (doCallbacks) {
      this->lock();
      /* Get the attributes for this driver */
      this->getAttributes(this->pArrays[0]->pAttributeList);
      /* Call any clients who have registered for NDArray callbacks */
      this->unlock();
      doCallbacksGenericPointer(this->pArrays[0], NDArrayData, 0);
    }
    if (pScratch) pScratch->release();
    /* We must enter the loop and exit with the mutex locked */
    this->lock();
    setIntegerParam(NDPluginProcessNumFiltered, this->numFiltered);
    callParamCallbacks();
    if (autoOffsetScale && this->pArrays[0] != NULL) {
        setIntegerParam(NDPluginProcessAutoOffsetScale, 0);
        callParamCallbacks();
    }
}
Exemple #3
0
/**
 * writeInt32. Write asyn integer values.
 */
asynStatus ADSBIG::writeInt32(asynUser *pasynUser, epicsInt32 value)
{
  asynStatus status = asynSuccess;
  int function = pasynUser->reason;
  int addr = 0;
  int adStatus = 0;
  PAR_ERROR cam_err = CE_NO_ERROR;
  MY_LOGICAL te_status = FALSE;
  double ccd_temp_set = 0;
  int minX = 0;
  int minY = 0;
  int sizeX = 0;
  int sizeY = 0;
  int binning = 0;
  const char *functionName = "ADSBIG::writeInt32";
  
  asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s Entry.\n", functionName);

  //Read the frame sizes 
  getIntegerParam(ADMinX, &minX);
  getIntegerParam(ADMinY, &minY);
  getIntegerParam(ADSizeX, &sizeX);
  getIntegerParam(ADSizeY, &sizeY);
  getIntegerParam(ADBinX, &binning);

  getIntegerParam(ADStatus, &adStatus);

  if (function == ADAcquire) {
    if ((value==1) && ((adStatus == ADStatusIdle) || (adStatus == ADStatusError) || (adStatus == ADStatusAborted))) {
      m_Acquiring = 1;
      m_aborted = false;
      setIntegerParam(ADStatus, ADStatusAcquire);
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s Start Event.\n", functionName);
      epicsEventSignal(this->m_startEvent);
    }
    if ((value==0) && ((adStatus != ADStatusIdle) && (adStatus != ADStatusError) && (adStatus != ADStatusAborted))) {
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s Abort Exposure.\n", functionName);
      abortExposure();
    }
  } else if (function == ADSBIGDarkFieldParam) {
    if (value == 1) {
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, 
                "%s Setting Dark Field Mode.\n", functionName);
    } else {
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, 
                "%s Setting Light Field Mode.\n", functionName);
    }
  } else if (function == ADSBIGReadoutModeParam) {
      p_Cam->SetReadoutMode(value);
      if (value == 0) {
        binning = 1;
      } else if (value == 1) {
        binning = 2;
      } else if (value == 2) {
        binning = 3;
      }
      //If we change the binning, reset the frame sizes. This forces
      //the frame sizes to be set after the binning mode.
      //The SubFrame sizes have the be set after we know the binning anyway.
      p_Cam->SetSubFrame(0, 0, m_CamWidth/binning, m_CamHeight/binning);
      setIntegerParam(ADMinX, 0);
      setIntegerParam(ADMinY, 0);
      setIntegerParam(ADSizeX, m_CamWidth/binning);
      setIntegerParam(ADSizeY, m_CamHeight/binning);
      setIntegerParam(ADBinX, binning);
      setIntegerParam(ADBinY, binning);
  } else if (function == ADSBIGTEStatusParam) {
    getDoubleParam(ADTemperature, &ccd_temp_set);
    if (value == 1) {
      te_status = TRUE;
    } else {
      te_status = FALSE;
    }
    if ((cam_err = p_Cam->SetTemperatureRegulation(te_status, ccd_temp_set)) != CE_NO_ERROR) {
      asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
                "%s. CSBIGCam::SetTemperatureRegulation returned an error. %s\n", 
                functionName, p_Cam->GetErrorString(cam_err).c_str());
      status = asynError;
    }
  } else if (function == ADMinX) {
    if (value > ((m_CamWidth/binning) - 1)) {
      value = (m_CamWidth/binning) - 1;
    }
    if ((value + sizeX) > (m_CamWidth/binning)) {
      sizeX = m_CamWidth/binning - value;
      setIntegerParam(ADSizeX, sizeX);
    }
  } else if (function == ADMinY) {
    if (value > ((m_CamHeight/binning) - 1)) {
      value = (m_CamHeight/binning) - 1;
    }
    if ((value + sizeY) > (m_CamHeight/binning)) {
      sizeY = m_CamHeight/binning - value;
      setIntegerParam(ADSizeY, sizeY);
    }
  } else if (function == ADSizeX) {
    if ((minX + value) > (m_CamWidth/binning)) {
      value = m_CamWidth/binning - minX;
    }
  } else if (function == ADSizeY) {
    if ((minY + value) > (m_CamHeight/binning)) {
      value = m_CamHeight/binning - minY;
    }
  }

  if (status != asynSuccess) {
    callParamCallbacks(addr);
    return asynError;
  }

  status = (asynStatus) setIntegerParam(addr, function, value);
  if (status!=asynSuccess) {
    asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
              "%s Error Setting Parameter. Asyn addr: %d, asynUser->reason: %d, value: %d\n", 
              functionName, addr, function, value);
    return(status);
  }

  //Do callbacks so higher layers see any changes 
  callParamCallbacks(addr);

  return status;
}
Exemple #4
0
/** Polls the axis.
  * This function reads the motor position, the limit status, the home status, the moving status, 
  * and the drive power-on status. 
  * It calls setIntegerParam() and setDoubleParam() for each item that it polls,
  * and then calls callParamCallbacks() at the end.
  * \param[out] moving A flag that is set indicating that the axis is moving (true) or done (false). */
asynStatus SMChydraAxis::poll(bool *moving)
{ 
  int done;
  int driveOn;
  int lowLimit;
  int highLimit;
  int ignoreLowLimit;
  int ignoreHighLimit;
  int axisStatus=-1;
  double position=0.0;
  asynStatus comStatus;

  static const char *functionName = "SMChydraAxis::poll";

  // Read the current motor position
  sprintf(pC_->outString_, "%i np", (axisNo_ + 1));
  comStatus = pC_->writeReadController();
  if (comStatus) goto skip;
  // The response string is a double
  position = atof( (char *) &pC_->inString_);
  setDoubleParam(pC_->motorPosition_, (position / axisRes_) );
  setDoubleParam(pC_->motorEncoderPosition_, (position / axisRes_) );
  
  // Read the status of this motor
  sprintf(pC_->outString_, "%i nst", (axisNo_ + 1));
  comStatus = pC_->writeReadController();
  if (comStatus) goto skip;
  // The response string is an int
  axisStatus = atoi( (char *) &pC_->inString_);
  
  // Check the moving bit
  done = !(axisStatus & 0x1);
  setIntegerParam(pC_->motorStatusDone_, done);
  setIntegerParam(pC_->motorStatusMoving_, !done);
  *moving = done ? false:true;

  // Read the commanded velocity and acceleration
  sprintf(pC_->outString_, "%i gnv", (axisNo_ + 1));
  comStatus = pC_->writeReadController();
  
  sprintf(pC_->outString_, "%i gna", (axisNo_ + 1));
  comStatus = pC_->writeReadController();

  // Check the limit bit (0x40)
  if (axisStatus & 0x40)
  {
    asynPrint(this->pasynUser_, ASYN_TRACEIO_DRIVER, 
      "%s: axis %i limit indicator active.\n",
      functionName, (axisNo_ + 1));
      
    // query limits?
  }

  // Check the e-stop bit (0x80)
  if (axisStatus & 0x80)
  {
    asynPrint(this->pasynUser_, ASYN_TRACEIO_DRIVER, 
      "%s: axis %i emergency stopped.\n",
      functionName, (axisNo_ + 1));
  }
  
  // Check the e-stop switch active bit (0x200)
  if (axisStatus & 0x200)
  {
    asynPrint(this->pasynUser_, ASYN_TRACEIO_DRIVER, 
      "%s: axis %i emergency stop switch active.\n",
      functionName, (axisNo_ + 1));
    setIntegerParam(pC_->motorStatusProblem_, 1);
  }
  else{
    setIntegerParam(pC_->motorStatusProblem_, 0);
  }

  // Check the device busy bit (0x400)
  if (axisStatus & 0x400)
  {
    asynPrint(this->pasynUser_, ASYN_TRACE_ERROR, 
      "%s: axis %i device is busy - move commands discarded.\n",
      functionName, (axisNo_ + 1));
  }

  // Read the limit status
  // Note: calibration switch = low limit; range measure switch = high limit
  // also need to read the switch confiruation to see if limits are ignored"

  // Read switch confiruation
  // Bit 0:	polarity (0 = NO, 1 = NC)
  // Bit 1:	mask (0 = enabled, 1 = disabled)
  sprintf(pC_->outString_, "%i getsw", (axisNo_ + 1));
  comStatus = pC_->writeReadController();
  if (comStatus) goto skip;
  sscanf(pC_->inString_, "%i %i", &lowLimitConfig_, &highLimitConfig_);
  ignoreLowLimit = lowLimitConfig_ & 0x2;
  ignoreHighLimit = highLimitConfig_ & 0x2;
  
  // Read status of switches 0=inactive 1=active
  sprintf(pC_->outString_, "%i getswst", (axisNo_ + 1));
  comStatus = pC_->writeReadController();
  if (comStatus) goto skip;
  // The response string is of the form "0 0"
  sscanf(pC_->inString_, "%i %i", &lowLimit, &highLimit);
  //
  if (ignoreLowLimit)
    setIntegerParam(pC_->motorStatusLowLimit_, 0);
  else
    setIntegerParam(pC_->motorStatusLowLimit_, lowLimit);

  if (ignoreHighLimit)
    setIntegerParam(pC_->motorStatusHighLimit_, 0);
  else
    setIntegerParam(pC_->motorStatusHighLimit_, highLimit);

  /*setIntegerParam(pC_->motorStatusAtHome_, limit);*/

  // Check the drive power bit (0x100)
  driveOn = (axisStatus & 0x100) ? 0 : 1;
  setIntegerParam(pC_->motorStatusPowerOn_, driveOn);
  setIntegerParam(pC_->motorStatusProblem_, 0);

  skip:
  setIntegerParam(pC_->motorStatusProblem_, comStatus ? 1:0);
  callParamCallbacks();
  return comStatus ? asynError : asynSuccess;
}
Exemple #5
0
asynStatus drvQuadEM::doDataCallbacks()
{
    epicsFloat64 doubleData[QE_MAX_DATA];
    epicsFloat64 *pIn, *pOut;
    int numAverage;
    int numAveraged;
    int sampleSize = sizeof(doubleData);
    int count;
    epicsTimeStamp now;
    epicsFloat64 timeStamp;
    int arrayCounter;
    int i, j;
    size_t dims[2];
    NDArray *pArrayAll, *pArraySingle;
    static const char *functionName = "doDataCallbacks";
    
    getIntegerParam(P_NumAverage, &numAverage);
    while (1) {
        numAveraged = epicsRingBytesUsedBytes(ringBuffer_) / sampleSize;
        if (numAverage > 0) {
            if (numAveraged < numAverage) break;
            numAveraged = numAverage;
            setIntegerParam(P_NumAveraged, numAveraged);
        } else {
            setIntegerParam(P_NumAveraged, numAveraged);
            if (numAveraged < 1) break;
        }

        dims[0] = QE_MAX_DATA;
        dims[1] = numAveraged;

        epicsTimeGetCurrent(&now);
        getIntegerParam(NDArrayCounter, &arrayCounter);
        arrayCounter++;
        setIntegerParam(NDArrayCounter, arrayCounter);

        pArrayAll = pNDArrayPool->alloc(2, dims, NDFloat64, 0, 0);
        pArrayAll->uniqueId = arrayCounter;
        timeStamp = now.secPastEpoch + now.nsec / 1.e9;
        pArrayAll->timeStamp = timeStamp;
        getAttributes(pArrayAll->pAttributeList);

        count = epicsRingBytesGet(ringBuffer_, (char *)pArrayAll->pData, numAveraged * sampleSize);
        if (count != numAveraged * sampleSize) {
            asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
                "%s:%s: ring read failed\n",
                driverName, functionName);
            return asynError;
        }
        ringCount_ -= numAveraged;
        unlock();
        doCallbacksGenericPointer(pArrayAll, NDArrayData, QE_MAX_DATA);
        lock();
        // Copy data to arrays for each type of data, do callbacks on that.
        dims[0] = numAveraged;
        for (i=0; i<QE_MAX_DATA; i++) {
            pArraySingle = pNDArrayPool->alloc(1, dims, NDFloat64, 0, 0);
            pArraySingle->uniqueId = arrayCounter;
            pArraySingle->timeStamp = timeStamp;
            getAttributes(pArraySingle->pAttributeList);
            pIn = (epicsFloat64 *)pArrayAll->pData;
            pOut = (epicsFloat64 *)pArraySingle->pData;
            for (j=0; j<numAveraged; j++) {
                pOut[j] = pIn[i];
                pIn += QE_MAX_DATA;
            }
            unlock();
            doCallbacksGenericPointer(pArraySingle, NDArrayData, i);
            lock();
            pArraySingle->release();
        }   
        pArrayAll->release();
        callParamCallbacks();
        // We only loop once if numAverage==0
        if (numAverage == 0) break;
    }    
    setIntegerParam(P_RingOverflows, 0);
    callParamCallbacks();
    return asynSuccess;
}
Exemple #6
0
/** Constructor for HDF5 driver; most parameters are simply passed to
  * ADDriver::ADDriver.
  * After calling the base class constructor this method creates a thread to
  * collect the detector data, and sets reasonable default values for the
  * parameters defined in this class, asynNDArrayDriver, and ADDriver.
  * \param[in] portName The name of the asyn port driver to be created.
  * \param[in] maxBuffers The maximum number of NDArray buffers that the
  *            NDArrayPool for this driver is allowed to allocate. Set this to
  *            -1 to allow an unlimited number of buffers.
  * \param[in] maxMemory The maximum amount of memory that the NDArrayPool for
  *            this driver is allowed to allocate. Set this to -1 to allow an
  *            unlimited amount of memory.
  * \param[in] priority The thread priority for the asyn port driver thread if
  *            ASYN_CANBLOCK is set in asynFlags.
  * \param[in] stackSize The stack size for the asyn port driver thread if
  *            ASYN_CANBLOCK is set in asynFlags.
  */
hdf5Driver::hdf5Driver (const char *portName, int maxBuffers, size_t maxMemory,
        int priority, int stackSize)
    : ADDriver(portName, 1, NUM_HDF5_PARAMS, maxBuffers, maxMemory,
            0, 0,             /* No interfaces beyond ADDriver.cpp */
            ASYN_CANBLOCK,    /* ASYN_CANBLOCK=1, ASYN_MULTIDEVICE=0 */
            1,                /* autoConnect=1 */
            priority, stackSize),
      mStartEventId(epicsEventCreate(epicsEventEmpty)),
      mStopEventId(epicsEventCreate(epicsEventEmpty)),
      mDatasetsCount(0), mpDatasets(NULL)
{
    int status = asynSuccess;
    const char *functionName = "hdf5Driver";

    if (!mStartEventId)
    {
        asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
                "%s:%s epicsEventCreate failure for start event\n",
                driverName, functionName);
        return;
    }

    if (!mStopEventId)
    {
        asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
                "%s:%s epicsEventCreate failure for stop event\n",
                driverName, functionName);
        return;
    }

    createParam(HDF5FilePathString,       asynParamOctet, &HDF5FilePath);
    createParam(HDF5FileExistsString,     asynParamInt32, &HDF5FileExists);
    createParam(HDF5DatasetsCountString,  asynParamInt32, &HDF5DatasetsCount);
    createParam(HDF5FirstFrameString,     asynParamInt32, &HDF5FirstFrame);
    createParam(HDF5LastFrameString,      asynParamInt32, &HDF5LastFrame);
    createParam(HDF5TotalFramesString,    asynParamInt32, &HDF5TotalFrames);
    createParam(HDF5CurrentFrameString,   asynParamInt32, &HDF5CurrentFrame);
    createParam(HDF5AutoLoadFrameString,  asynParamInt32, &HDF5AutoLoadFrame);
    createParam(HDF5LoopString,           asynParamInt32, &HDF5Loop);

    status = asynSuccess;

    status |= setStringParam (HDF5FilePath,         "");
    status |= setIntegerParam(HDF5FileExists,       0);
    status |= setIntegerParam(HDF5FirstFrame,       0);
    status |= setIntegerParam(HDF5LastFrame,        0);
    status |= setIntegerParam(HDF5TotalFrames,      0);
    status |= setIntegerParam(HDF5CurrentFrame,     0);
    status |= setIntegerParam(HDF5AutoLoadFrame,    0);
    status |= setIntegerParam(HDF5Loop,             0);
    status |= setDoubleParam (ADAcquirePeriod,      0.02);

    callParamCallbacks();

    if (status)
    {
        printf("%s: unable to set driver parameters\n", functionName);
        return;
    }

    /* Create the thread that updates the images */
    status = (epicsThreadCreate("hdf5DrvTask", epicsThreadPriorityMedium,
            epicsThreadGetStackSize(epicsThreadStackMedium),
            (EPICSTHREADFUNC)hdf5TaskC, this) == NULL);

    if (status)
    {
        asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
                "%s:%s epicsThreadCreate failure for task\n",
                driverName, functionName);
        return;
    }
}
Exemple #7
0
/** 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, &currentFrame);
        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,   &currentFrame);
            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;
    }
}
asynStatus NDPluginAttribute::writeInt32(asynUser *pasynUser, epicsInt32 value)
{
  int function = pasynUser->reason;
  asynStatus status = asynSuccess;
  int numTSPoints, currentTSPoint;
  int i;
  static const char *functionName = "NDPluginAttribute::writeInt32";

  /* Set the parameter in the parameter library. */
  status = (asynStatus) setIntegerParam(function, value);

  if (function == NDPluginAttributeReset) {
  getIntegerParam(NDPluginAttributeTSNumPoints, &numTSPoints);
    for (i=0; i<maxAttributes_; i++) {
      setDoubleParam(i, NDPluginAttributeVal, 0.0);
      setDoubleParam(i, NDPluginAttributeValSum, 0.0);
      // Clear the time series array
      memset(pTSArray_[i], 0, numTSPoints*sizeof(epicsFloat64));
      doCallbacksFloat64Array(this->pTSArray_[i], numTSPoints, NDPluginAttributeTSArrayValue, i);
      callParamCallbacks(i);
    }
    setIntegerParam(NDPluginAttributeTSCurrentPoint, 0);
  } 
  else if (function == NDPluginAttributeTSNumPoints) {
    for (i=0; i<maxAttributes_; i++) {
      free(pTSArray_[i]);
      pTSArray_[i] = static_cast<epicsFloat64 *>(calloc(value, sizeof(epicsFloat64)));
    }
  } 
  else if (function == NDPluginAttributeTSControl) {
    switch (value) {
      case TSEraseStart:
        setIntegerParam(NDPluginAttributeTSCurrentPoint, 0);
        setIntegerParam(NDPluginAttributeTSAcquiring, 1);
        getIntegerParam(NDPluginAttributeTSNumPoints, &numTSPoints);
        for (i=0; i<maxAttributes_; i++) {
          memset(pTSArray_[i], 0, numTSPoints*sizeof(epicsFloat64));
        }
        doTimeSeriesCallbacks();
        break;
      case TSStart:
        getIntegerParam(NDPluginAttributeTSNumPoints, &numTSPoints);
        getIntegerParam(NDPluginAttributeTSCurrentPoint, &currentTSPoint);
        if (currentTSPoint < numTSPoints) {
          setIntegerParam(NDPluginAttributeTSAcquiring, 1);
        }
        break;
      case TSStop:
        setIntegerParam(NDPluginAttributeTSAcquiring, 0);
        doTimeSeriesCallbacks();
        break;
      case TSRead:
        doTimeSeriesCallbacks();
        break;
    }
  }
  else {
    /* If this parameter belongs to a base class call its method */
    if (function < FIRST_NDPLUGIN_ATTR_PARAM) 
      status = NDPluginDriver::writeInt32(pasynUser, value);
  }

  /* Do callbacks so higher layers see any changes */
  status = (asynStatus) callParamCallbacks();

  if (status) 
    epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize, 
                  "%s: status=%d, function=%d, value=%d", 
                  functionName, status, function, value);
  else        
    asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, 
              "%s: function=%d, value=%d\n", 
              functionName, function, value);
  return status;
}
/** 
  * \param[in] pArray  The NDArray from the callback.
  */
void NDPluginAttribute::processCallbacks(NDArray *pArray)
{
  /*
     * This function is called with the mutex already locked.  It unlocks it during long calculations when private
     * structures don't need to be protected.
     */

  int status = 0;
  int currentTSPoint;
  int numTSPoints;
  int TSAcquiring;
  double valueSum;
  int i;
  char attrName[MAX_ATTR_NAME_] = {0};
  NDAttribute *pAttribute = NULL;
  NDAttributeList *pAttrList = NULL;
  epicsFloat64 attrValue = 0.0;

  static const char *functionName = "NDPluginAttribute::processCallbacks";
  
  /* Call the base class method */
  NDPluginDriver::beginProcessCallbacks(pArray);
  
  /* Get the attributes for this driver */
  pAttrList = pArray->pAttributeList;
  
  getIntegerParam(NDPluginAttributeTSCurrentPoint, &currentTSPoint);
  getIntegerParam(NDPluginAttributeTSNumPoints,    &numTSPoints);
  getIntegerParam(NDPluginAttributeTSAcquiring,    &TSAcquiring);

  for (i=0; i<maxAttributes_; i++) {
    getStringParam(i, NDPluginAttributeAttrName, MAX_ATTR_NAME_, attrName);

    asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "Finding the attribute %s\n", attrName);

    if (strcmp(attrName, UNIQUE_ID_NAME_) == 0) {
      attrValue = (epicsFloat64) pArray->uniqueId;
    } else if (strcmp(attrName, TIMESTAMP_NAME_) == 0) {
      attrValue = pArray->timeStamp;
    } else if (strcmp(attrName, EPICS_TS_SEC_NAME_) == 0) {
      attrValue = (epicsFloat64)pArray->epicsTS.secPastEpoch;
    } else if (strcmp(attrName, EPICS_TS_NSEC_NAME_) == 0) {
      attrValue = (epicsFloat64)pArray->epicsTS.nsec;
    } else {
      pAttribute = pAttrList->find(attrName);
      if (pAttribute) {
        status = pAttribute->getValue(NDAttrFloat64, &attrValue);
        if (status != asynSuccess) {
          asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s: Error reading value for NDAttribute %s. \n", functionName, attrName);
          continue;
        }
        asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "Attribute %s value is %f\n", attrName, attrValue);
      } else {
        asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s: Error finding NDAttribute %s. \n", functionName, attrName);
        continue;
      }
    }
    setDoubleParam(i, NDPluginAttributeVal, attrValue);
    getDoubleParam(i, NDPluginAttributeValSum, &valueSum);
    valueSum += attrValue;
    setDoubleParam(i, NDPluginAttributeValSum, valueSum);
    if (TSAcquiring) {
      pTSArray_[i][currentTSPoint] = attrValue;
    }
    callParamCallbacks(i);
  }
  if (TSAcquiring) {
    currentTSPoint++;
    setIntegerParam(NDPluginAttributeTSCurrentPoint, currentTSPoint);
    if (currentTSPoint >= numTSPoints) {
        doTimeSeriesCallbacks();
        setIntegerParam(NDPluginAttributeTSAcquiring, 0);
    }
  }
}
Exemple #10
0
/** Called when asyn clients call pasynInt32->write().
  * This function performs actions for some parameters, including NDReadFile, NDWriteFile and NDFileCapture.
  * For other parameters it calls NDPluginDriver::writeInt32 to see if that method understands the parameter. 
  * For all parameters it sets the value in the parameter library and calls any registered callbacks..
  * \param[in] pasynUser pasynUser structure that encodes the reason and address.
  * \param[in] value Value to write. */
asynStatus NDPluginFile::writeInt32(asynUser *pasynUser, epicsInt32 value)
{
    int function = pasynUser->reason;
    asynStatus status = asynSuccess;
    static const char* functionName = "writeInt32";

    /* Set the parameter in the parameter library. */
    status = (asynStatus) setIntegerParam(function, value);

    if (function == NDWriteFile) {
        if (value) {
            /* Call the callbacks so the status changes */
            callParamCallbacks();
            if (this->pArrays[0]) {
                status = writeFileBase();
            } else {
                asynPrint(pasynUser, ASYN_TRACE_ERROR,
                    "%s::%s: ERROR, no valid array to write",
                    driverName, functionName);
                status = asynError;
            }
            /* Set the flag back to 0, since this could be a busy record */
            setIntegerParam(NDWriteFile, 0);
        }
    } else if (function == NDReadFile) {
        if (value) {
            /* Call the callbacks so the status changes */
            callParamCallbacks();
            status = readFileBase();
            /* Set the flag back to 0, since this could be a busy record */
            setIntegerParam(NDReadFile, 0);
        }
    } else if (function == NDFileCapture) {
        if (value) {  // Started capture or stream
            // Reset the value temporarily until the doCapture() has called the
            // inherited openFile() method and the writer is in a good state to
            // start writing frames.
            // See comments on: https://github.com/areaDetector/ADCore/pull/100
            setIntegerParam(NDFileCapture, 0);

            /* Latch the NDFileLazyOpen parameter so that we don't need to care
             * if the user modifies this parameter before first frame has arrived. */
            int paramFileLazyOpen = 0;
            getIntegerParam(NDFileLazyOpen, &paramFileLazyOpen);
            this->lazyOpen = (paramFileLazyOpen != 0);
            /* So far everything is OK, so we just clear the FileWriteStatus parameters */
            setIntegerParam(NDFileWriteStatus, NDFileWriteOK);
            setStringParam(NDFileWriteMessage, "");
            setStringParam(NDFullFileName, "");
        }
        /* Must call doCapture if capturing was just started or stopped */
        status = doCapture(value);
        if (status == asynSuccess) {
            if (this->lazyOpen) setStringParam(NDFileWriteMessage, "Lazy Open...");
            setIntegerParam(NDFileCapture, value);
        } else {
            setIntegerParam(NDFileCapture, 0);
        }
    } else {
        /* This was not a parameter that this driver understands, try the base class */
        status = NDPluginDriver::writeInt32(pasynUser, value);
    }
    
    /* Do callbacks so higher layers see any changes */
    status = callParamCallbacks();
    
    if (status) 
        asynPrint(pasynUser, ASYN_TRACE_ERROR, 
              "%s::%s error, status=%d function=%d, value=%d\n", 
              driverName, functionName, status, function, value);
    else        
        asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, 
              "%s::%s: function=%d, value=%d\n", 
              driverName, functionName, function, value);
    return status;
}
Exemple #11
0
/** Callback function that is called by the NDArray driver with new NDArray data.
  * Draws overlays on top of the array.
  * \param[in] pArray  The NDArray from the callback.
  */
void NDPluginOverlay::processCallbacks(NDArray *pArray)
{
    /* This function draws overlays
     * It is called with the mutex already locked.  It unlocks it during long calculations when private
     * structures don't need to be protected.
     */

    int use;
    int itemp;
    int overlay;
    NDArray *pOutput;
    //static const char* functionName = "processCallbacks";

    /* Call the base class method */
    NDPluginDriver::processCallbacks(pArray);

    /* We always keep the last array so read() can use it.
     * Release previous one. */
    if (this->pArrays[0]) {
        this->pArrays[0]->release();
    }
    /* Copy the input array so we can modify it. */
    this->pArrays[0] = this->pNDArrayPool->copy(pArray, NULL, 1);
    pOutput = this->pArrays[0];
    
    /* Get information about the array needed later */
    pOutput->getInfo(&this->arrayInfo);
    setIntegerParam(NDPluginOverlayMaxSizeX, (int)arrayInfo.xSize);
    setIntegerParam(NDPluginOverlayMaxSizeY, (int)arrayInfo.ySize);
   
    /* Loop over the overlays in this driver */
    for (overlay=0; overlay<this->maxOverlays; overlay++) {
        pOverlay = &this->pOverlays[overlay];
        getIntegerParam(overlay, NDPluginOverlayUse, &use);
        asynPrint(pasynUserSelf, ASYN_TRACEIO_DRIVER,
            "NDPluginOverlay::processCallbacks, overlay=%d, use=%d\n",
            overlay, use);
        if (!use) continue;
        /* Need to fetch all of these parameters while we still have the mutex */
        getIntegerParam(overlay, NDPluginOverlayPositionX,  &itemp); pOverlay->PositionX = itemp;
        pOverlay->PositionX = MAX(pOverlay->PositionX, 0);
        pOverlay->PositionX = MIN(pOverlay->PositionX, this->arrayInfo.xSize-1);
        getIntegerParam(overlay, NDPluginOverlayPositionY,  &itemp); pOverlay->PositionY = itemp;
        pOverlay->PositionY = MAX(pOverlay->PositionY, 0);
        pOverlay->PositionY = MIN(pOverlay->PositionY, this->arrayInfo.ySize-1);
        getIntegerParam(overlay, NDPluginOverlaySizeX,      &itemp); pOverlay->SizeX = itemp;
        getIntegerParam(overlay, NDPluginOverlaySizeY,      &itemp); pOverlay->SizeY = itemp;
        getIntegerParam(overlay, NDPluginOverlayWidthX,     &itemp); pOverlay->WidthX = itemp;
        getIntegerParam(overlay, NDPluginOverlayWidthY,     &itemp); pOverlay->WidthY = itemp;
        getIntegerParam(overlay, NDPluginOverlayShape,      &itemp); pOverlay->shape = (NDOverlayShape_t)itemp;
        getIntegerParam(overlay, NDPluginOverlayDrawMode,   &itemp); pOverlay->drawMode = (NDOverlayDrawMode_t)itemp;
        getIntegerParam(overlay, NDPluginOverlayRed,        &pOverlay->red);
        getIntegerParam(overlay, NDPluginOverlayGreen,      &pOverlay->green);
        getIntegerParam(overlay, NDPluginOverlayBlue,       &pOverlay->blue);
        getStringParam( overlay, NDPluginOverlayTimeStampFormat, sizeof(pOverlay->TimeStampFormat), pOverlay->TimeStampFormat);
        getIntegerParam(overlay, NDPluginOverlayFont,       &pOverlay->Font);
        getStringParam( overlay, NDPluginOverlayDisplayText, sizeof(pOverlay->DisplayText), pOverlay->DisplayText);

        pOverlay->DisplayText[sizeof(pOverlay->DisplayText)-1] = 0;

        /* This function is called with the lock taken, and it must be set when we exit.
         * The following code can be exected without the mutex because we are not accessing memory
         * that other threads can access. */
        this->unlock();
        this->doOverlay(pOutput, pOverlay);
        this->lock();
    }
    /* Get the attributes for this driver */
    this->getAttributes(this->pArrays[0]->pAttributeList);
    /* Call any clients who have registered for NDArray callbacks */
    this->unlock();
    doCallbacksGenericPointer(this->pArrays[0], NDArrayData, 0);
    this->lock();
    callParamCallbacks();
}
Exemple #12
0
/** Base method for writing a file
  * Handles logic for NDFileModeSingle, NDFileModeCapture and NDFileModeStream when the derived class does or
  * does not support NDPulginFileMultiple. Calls writeFile in the derived class. */
asynStatus NDPluginFile::writeFileBase() 
{
    int status = asynSuccess;
    int fileWriteMode;
    int numCapture, numCaptured;
    int i;
    bool doLazyOpen;
    int deleteDriverFile;
    NDArray *pArray;
    NDAttribute *pAttribute;
    char driverFileName[MAX_FILENAME_LEN];
    char errorMessage[256];
    static const char* functionName = "writeFileBase";

    /* Make sure there is a valid array */
    if (!this->pArrays[0]) {
        asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
            "%s::%s: ERROR, must collect an array to get dimensions first\n",
            driverName, functionName);
        return(asynError);
    }
    
    NDArray *pArrayOut = this->pArrays[0];
    // Must increase reference count on this array because another thread might decrement the count on pArrays[0]
    // when we have the mutex unlocked
    pArrayOut->reserve();

    getIntegerParam(NDFileWriteMode, &fileWriteMode);    
    getIntegerParam(NDFileNumCapture, &numCapture);    
    getIntegerParam(NDFileNumCaptured, &numCaptured);

    setIntegerParam(NDFileWriteStatus, NDFileWriteOK);
    setStringParam(NDFileWriteMessage, "");
    
    /* We unlock the overall mutex here because we want the callbacks to be able to queue new
     * frames without waiting while we write files here.  The only restriction is that the
     * callbacks must not modify any part of the class structure that we use here. */

    switch(fileWriteMode) {
        case NDFileModeSingle:
            setIntegerParam(NDWriteFile, 1);
            callParamCallbacks();
            // Some file writing plugins (e.g. HDF5) use the value of NDFileNumCaptured 
            // even in single mode
            setIntegerParam(NDFileNumCaptured, 1);
            status = this->openFileBase(NDFileModeWrite, pArrayOut);
            if (status == asynSuccess) {
                this->unlock();
                epicsMutexLock(this->fileMutexId);
                status = this->writeFile(pArrayOut);
                epicsMutexUnlock(this->fileMutexId);
                this->lock();
                NDPluginDriver::endProcessCallbacks(pArrayOut, true, true);
                if (status) {
                    epicsSnprintf(errorMessage, sizeof(errorMessage)-1, 
                        "Error writing file, status=%d", status);
                    asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
                          "%s::%s %s\n", 
                          driverName, functionName, errorMessage);
                    setIntegerParam(NDFileWriteStatus, NDFileWriteError);
                    setStringParam(NDFileWriteMessage, errorMessage);
                } else {
                    status = this->closeFileBase(); 
                }
            }
            setIntegerParam(NDWriteFile, 0);
            callParamCallbacks();
            break;
        case NDFileModeCapture:
            /* Write the file */
            if (!this->pCapture) {
                asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
                    "%s::%s: ERROR, no capture buffer present\n", 
                    driverName, functionName);
                setIntegerParam(NDFileWriteStatus, NDFileWriteError);
                setStringParam(NDFileWriteMessage, "ERROR, no capture buffer present");
                break;
            }
            setIntegerParam(NDWriteFile, 1);
            callParamCallbacks();
            if (this->supportsMultipleArrays)
                status = this->openFileBase(NDFileModeWrite | NDFileModeMultiple, pArrayOut);
            if (status == asynSuccess) {
                for (i=0; i<numCaptured; i++) {
                    pArray = this->pCapture[i];
                    if (!this->supportsMultipleArrays)
                        status = this->openFileBase(NDFileModeWrite, pArray);
                    else
                        this->attrFileNameCheck();
                    if (status == asynSuccess) {
                        this->unlock();
                        epicsMutexLock(this->fileMutexId);
                        status = this->writeFile(pArray);
                        epicsMutexUnlock(this->fileMutexId);
                        this->lock();
                        NDPluginDriver::endProcessCallbacks(pArray, true, true);
                        if (status) {
                            epicsSnprintf(errorMessage, sizeof(errorMessage)-1, 
                                "Error writing file, status=%d", status);
                            asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
                                  "%s::%s %s\n", 
                                  driverName, functionName, errorMessage);
                            setIntegerParam(NDFileWriteStatus, NDFileWriteError);
                            setStringParam(NDFileWriteMessage, errorMessage);
                        } else {
                            if (!this->supportsMultipleArrays)
                                status = this->closeFileBase();
                        }
                    }
                }
            }
            freeCaptureBuffer(numCapture);
            if ((status == asynSuccess) && this->supportsMultipleArrays) 
                status = this->closeFileBase();
            this->registerInitFrameInfo(NULL);
            setIntegerParam(NDFileNumCaptured, 0);
            setIntegerParam(NDWriteFile, 0);
            callParamCallbacks();
            break;
        case NDFileModeStream:
            doLazyOpen = this->lazyOpen && (numCaptured == 0);
            if (!this->supportsMultipleArrays || doLazyOpen)
                status = this->openFileBase(NDFileModeWrite | NDFileModeMultiple, pArrayOut);
            else
                this->attrFileNameCheck();
            if (!this->isFrameValid(pArrayOut)) {
                setIntegerParam(NDFileWriteStatus, NDFileWriteError);
                setStringParam(NDFileWriteMessage, "Invalid frame. Ignoring.");
                status = asynError;
            }
            if (status == asynSuccess) {
                this->unlock();
                epicsMutexLock(this->fileMutexId);
                status = this->writeFile(pArrayOut);
                epicsMutexUnlock(this->fileMutexId);
                this->lock();
                NDPluginDriver::endProcessCallbacks(pArrayOut, true, true);
                if (status) {
                    epicsSnprintf(errorMessage, sizeof(errorMessage)-1,
                            "Error writing file, status=%d", status);
                    asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
                            "%s::%s %s\n",
                            driverName, functionName, errorMessage);
                    setIntegerParam(NDFileWriteStatus, NDFileWriteError);
                    setStringParam(NDFileWriteMessage, errorMessage);
                } else {
                    status = this->attrFileCloseCheck();
                    if (!this->supportsMultipleArrays)
                        status = this->closeFileBase();
                }
            }
            break;
        default:
            asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
                "%s::%s: ERROR, unknown fileWriteMode %d\n", 
                driverName, functionName, fileWriteMode);
            break;
    }
    
    /* Check to see if we should delete the original file
     * Only do this if all of the following conditions are met
     *  - DeleteOriginalFile is true
     *  - There were no errors above
     *  - The NDFullFileName attribute is present and contains a non-blank string
     */
    getIntegerParam(NDFileDeleteDriverFile, &deleteDriverFile);
    if ((status == asynSuccess) && deleteDriverFile) {
        pAttribute = pArrayOut->pAttributeList->find("DriverFileName");
        if (pAttribute) {
            status = pAttribute->getValue(NDAttrString, driverFileName, sizeof(driverFileName));
            if ((status == asynSuccess) && (strlen(driverFileName) > 0)) {
                status = remove(driverFileName);
                if (status != 0) {
                    asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
                              "%s::%s: error deleting file %s, error=%s\n",
                              driverName, functionName, driverFileName, strerror(errno));
                }
            }
        }
    }

    // Decrease reference count
    pArrayOut->release();

    return (asynStatus) status;
}
Exemple #13
0
epicsInt32 mythen::dataCallback(epicsInt32 *pData)
{
    NDArray *pImage; 
    int ndims = 1;
    size_t dims[2];
    int totalBytes; 
    int arrayCallbacks;
    int imageCounter;
    epicsTimeStamp timeStamp; 
    epicsInt32 colorMode = NDColorModeMono;

    // printf ("pData[0] = %X\n",pData[0]);

    if (pData == NULL || pData[0] < 0) return(0); 

    dims[0] = MAX_DIMS;
    dims[1] = 1;
    totalBytes = this->nmodules*MAX_DIMS*sizeof(epicsInt32);

    /* Get the current time */
    epicsTimeGetCurrent(&timeStamp); 

    /* Allocate a new image buffer */
    pImage = this->pNDArrayPool->alloc(ndims, dims, NDInt32, totalBytes, NULL);
    if (readmode_==0)
      decodeRawReadout(this->nmodules, this->nbits_, pData, (int *)pImage->pData);
    else
      decodeRawReadout(this->nmodules, 24, pData, (int *)pImage->pData);
    //    memcpy(pImage->pData,  pData, totalBytes); 
    pImage->dataType = NDUInt32;
    pImage->ndims = ndims; 
    pImage->dims[0].size = dims[0]; 
    pImage->dims[0].offset = 0; 
    pImage->dims[0].binning = 1; 
    pImage->dims[1].size = dims[1]; 
    pImage->dims[1].offset = 0; 
    pImage->dims[1].binning = 1; 

    pImage->pAttributeList->add("ColorMode", "Color Mode", NDAttrInt32, &colorMode);

    /* Increase image counter */
    getIntegerParam(NDArrayCounter, &imageCounter);
    imageCounter++;
    setIntegerParam(NDArrayCounter, imageCounter);

    /* Set the uniqueId and time stamp */
    pImage->uniqueId = imageCounter; 
    pImage->timeStamp = timeStamp.secPastEpoch + timeStamp.nsec / 1e9; 

    /* Get any attributes that have been defined for this driver */        
    this->getAttributes(pImage->pAttributeList);

    getIntegerParam(NDArrayCallbacks, &arrayCallbacks);
    if (arrayCallbacks) {
        /* Call the NDArray callback */
        /* Must release the lock here, or we can get into a deadlock, because we can
         * block on the plugin lock, and the plugin can be calling us */
        this->unlock();
        doCallbacksGenericPointer(pImage, NDArrayData, 0);
        this->lock();
    }

    /* We save the most recent good image buffer so it can be used in the
     * readADImage function.  Now release it. */
    if (this->pArrays[0]) this->pArrays[0]->release();
    this->pArrays[0] = pImage;

    /* Update any changed parameters */
    callParamCallbacks();

    return(1);
}
Exemple #14
0
void mythen::acquisitionTask()
{
    size_t nread, nread_expect;
    size_t nwrite;
    int eventStatus;
    int imageMode;
    epicsInt32 acquire, eomReason;
    double acquireTime;
    asynStatus status = asynSuccess;
    int dataOK;

    static const char *functionName = "acquisitionTask";
    this->lock(); 

    while (1) {
        /* Is acquisition active? */
        getIntegerParam(ADAcquire, &acquire);
        
        /* If we are not acquiring then wait for a semaphore that is given when acquisition is started */
        if (!acquire || !acquiring_)  {
            setIntegerParam(ADStatus, ADStatusIdle);
            callParamCallbacks();
            /* Release the lock while we wait for an event that says acquire has started, then lock again */
            asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, 
                "%s:%s: waiting for acquire to start\n", driverName, functionName);
            this->unlock();
            eventStatus = epicsEventWait(this->startEventId_);
            // setStringParam(ADStatusMessage, "Acquiring data");
            // setIntegerParam(ADNumImagesCounter, 0);
              // getIntegerParam(ADAcquire, &acquire);
              
                  
              //printf("Read Mode: %d\tnModules: %d\t chanperline: %d\n", readmode_,this->nmodules,chanperline_);
            if (readmode_==0)       //Raw Mode
                nread_expect = sizeof(epicsInt32)*this->nmodules*(1280/chanperline_);
            else
                nread_expect = sizeof(epicsInt32)*this->nmodules*(1280);
                
            dataOK = 1;

            eventStatus = getStatus();
            setIntegerParam(ADStatus, eventStatus);

            if (eventStatus!=ADStatusError) {

              getDoubleParam(ADAcquireTime,&acquireTime);
              // printf("Acquisition start - expect %d\n",nread_expect);
              // Work on the cases of what are you getting from getstatus
              do {
                nread=0;
                if (readmode_==0)
                  strcpy(outString_, "-readoutraw");
                else
                  strcpy(outString_, "-readout");

                status = pasynOctetSyncIO->writeRead(pasynUserMeter_, outString_, strlen(outString_), (char *)detArray_,
                                        nread_expect, M1K_TIMEOUT+acquireTime, &nwrite, &nread, &eomReason);  //Timeout is M1K_TIMEOUT + AcquireTime

                //printf("nread_expected = %d\tnread = %d\n", nread_expect,nread);

                if(nread == nread_expect) {
                    this->lock();
                    dataOK = dataCallback(detArray_);
                    this->unlock();
                    if (!dataOK) {
                        eventStatus = getStatus();
                        setIntegerParam(ADStatus, eventStatus);
                    }

                }
                else {
                    eventStatus = getStatus();
                    setIntegerParam(ADStatus, eventStatus);
                  //printf("Data not size expected ADStatus: %d\n",eventStatus);
                }
                if(status != asynSuccess) {
                    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
                          "%s:%s: error using readout command status=%d, nRead=%d, eomReason=%d\n",
                          driverName, functionName, status, (int)nread, eomReason);
                }
              } 
              while (status == asynSuccess && (eventStatus==ADStatusAcquire||eventStatus==ADStatusReadout) && acquiring_);
             
           }
           this->lock();
            
        }
        if (eventStatus!=ADStatusError ) {
          printf("Acquisition finish\n");
          getIntegerParam(ADImageMode, &imageMode);
          if (imageMode == ADImageSingle || imageMode == ADImageMultiple) {
            printf("ADAcquire Callback\n");
            acquiring_ = 0;
            setIntegerParam(ADAcquire,  0); 
            callParamCallbacks(); 
          }
        }
        else {
          //Abort read 
          asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
                "%s:%s: error timed out waiting for data\n",
                driverName, functionName);
          acquiring_ = 0;
            setAcquire(0);
          setIntegerParam(ADAcquire,  0); 
          callParamCallbacks(); 
        }
    }
}
asynStatus isisdaeDriver::writeOctet(asynUser *pasynUser, const char *value, size_t maxChars, size_t *nActual)
{
    int function = pasynUser->reason;
    asynStatus status = asynSuccess;
    const char *paramName = NULL;
	getParamName(function, &paramName);
    const char* functionName = "writeOctet";
	std::string value_s;
    // we might get an embedded NULL from channel access char waveform records
    if ( (maxChars > 0) && (value[maxChars-1] == '\0') )
    {
        value_s.assign(value, maxChars-1);
    }
    else
    {
        value_s.assign(value, maxChars);
    }
	m_iface->resetMessages();
	try
	{
        if (function == P_RunTitle)
        {
			m_iface->setRunTitle(value_s);
        }
        else if (function == P_SamplePar)
        {
            std::vector<std::string> tokens;
            boost::split(tokens, value_s, boost::is_any_of("\2")); //  name, type, units, value
            if (tokens.size() == 4)
            {
				translateBeamlineType(tokens[1]);
                m_iface->setSampleParameter(tokens[0], tokens[1], tokens[2], tokens[3]);
            }
            else
            {
                throw std::runtime_error("SampleParameter: not enough tokens");
            }
        }
        else if (function == P_BeamlinePar)
        {
            std::vector<std::string> tokens;
            boost::split(tokens, value_s, boost::is_any_of("\2")); //  name, type, units, value
            if (tokens.size() == 4)
            {
				translateBeamlineType(tokens[1]);
                m_iface->setBeamlineParameter(tokens[0], tokens[1], tokens[2], tokens[3]);
            }
            else
            {
                throw std::runtime_error("BeamlineParameter: not enough tokens");
            }
        }
        else if (function == P_RBNumber)
        {
            char user[256];
            getStringParam(P_UserName, sizeof(user), user);
            m_iface->setUserParameters(atol(value_s.c_str()), user, "", "");
        }
        else if (function == P_UserName)
        {
            char rbno[16];
            getStringParam(P_RBNumber, sizeof(rbno), rbno);
            m_iface->setUserParameters(atol(rbno), value_s, "", "");
        }
        else if (function == P_DAESettings)
		{
			m_iface->setDAESettingsXML(value_s);
		}
        else if (function == P_HardwarePeriodsSettings)
		{
			m_iface->setHardwarePeriodsSettingsXML(value_s);
		}
        else if (function == P_UpdateSettings)
		{
			m_iface->setUpdateSettingsXML(value_s);
		}
        else if (function == P_TCBSettings)
		{
		    std::string tcb_xml;
		    if (uncompressString(value_s, tcb_xml) == 0)
			{
                unsigned found = tcb_xml.find_last_of(">");  // in cased junk on end
                m_iface->setTCBSettingsXML(tcb_xml.substr(0,found+1));
			}
		}        
        else if (function == P_SnapshotCRPT)
		{
		    beginStateTransition(RS_STORING);
			m_iface->snapshotCRPT(value_s, 1, 1);
            endStateTransition();
		}        
        
		reportMessages();
		status = asynPortDriver::writeOctet(pasynUser, value_s.c_str(), value_s.size(), nActual);
        asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, 
              "%s:%s: function=%d, name=%s, value=%s\n", 
              driverName, functionName, function, paramName, value_s.c_str());
        if (status == asynSuccess)
        {
		    *nActual = maxChars;   // to keep result happy in case we skipped an embedded trailing NULL
        }
		return status;
	}
	catch(const std::exception& ex)
	{
        epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize, 
                  "%s:%s: status=%d, function=%d, name=%s, value=%s, error=%s", 
                  driverName, functionName, status, function, paramName, value_s.c_str(), ex.what());
		reportErrors(ex.what());
		callParamCallbacks(); // this flushes P_ErrMsgs
        endStateTransition();
		*nActual = 0;
		return asynError;
	}
}
Exemple #16
0
void ecAsyn::on_pdo_message(PDO_MESSAGE * pdo, int size)
{
    lock();
    char * meta = pdo->buffer + pdo->size + SLAVE_METADATA_CNT * devid;
    assert(meta + 1 - pdo->buffer < size);
    epicsInt32 slave_info = meta[0];
    epicsInt32 al_state = meta[1];
    epicsInt32 error_flag = meta[2];
    epicsInt32 disable = pdo->wc_state != EC_WC_COMPLETE
        || al_state != EC_AL_STATE_OP
        || slave_info != 0;
    asynStatus paramStatus = asynSuccess;
    if (slave_info != 0)
    {
        paramStatus = asynDisconnected;
    }
    // perhaps set paramStatus to
    // asynDisabled if pdo->wc_state != EC_WC_COMPLETE
    setIntegerParam(P_SLAVEINFO, slave_info);
    setIntegerParam(P_AL_STATE, al_state);
    setParamStatus(P_AL_STATE, paramStatus);
    setIntegerParam(P_ERROR_FLAG, error_flag);
    setParamStatus(P_ERROR_FLAG, paramStatus);
    setIntegerParam(P_DISABLE, disable);
    setParamStatus(P_DISABLE, paramStatus);

    for(ELLNODE * node = ellFirst(&device->pdo_entry_mappings); node; node = ellNext(node))
    {
        EC_PDO_ENTRY_MAPPING * mapping = (EC_PDO_ENTRY_MAPPING *)node;
        int mpdoe_param = mapping->pdo_entry->parameter;
        if (mapping->pdo_entry->datatype[0] == 'F')
        {
            double val = cast_double(mapping, pdo->buffer, 0);
            if (disable)
            {
                setDoubleParam(mpdoe_param, MINFLOAT);
            }
            else
            {
                setDoubleParam(mpdoe_param, val);
            }
            setParamStatus(mpdoe_param, paramStatus);
        }
        else
        {
	        int32_t val = cast_int32(mapping, pdo->buffer, 0);
	        // can't make SDIS work with I/O intr (some values get lost)
	        // so using this for now
	        if(disable)
	        {
	            setIntegerParam(mpdoe_param, INT32_MIN);
	        }
	        else
	        {
	            setIntegerParam(mpdoe_param, val);
	        }
            setParamStatus(mpdoe_param, paramStatus);
        }
    }
    callParamCallbacks();
    unlock();
}
void isisdaeDriver::pollerThread2()
{
    static const char* functionName = "isisdaePoller2";
	std::map<std::string, DAEValue> values;
    unsigned long counter = 0;
    double delay = 2.0;  
    long this_rf = 0, this_gf = 0, last_rf = 0, last_gf = 0;
    bool check_settings;
    std::string daeSettings;
    std::string tcbSettings, tcbSettingComp;
    std::string hardwarePeriodsSettings;
    std::string updateSettings;
    std::string vetoStatus;

    lock();
	while(true)
	{
        unlock();
		epicsThreadSleep(delay);
		lock();
        if (m_inStateTrans)   // do nothing if in state transition
        {
            continue;
        }
        check_settings = ( (counter == 0) || (m_RunStatus == RS_SETUP && counter % 2 == 0) || (counter % 10 == 0) );
        try
        {
            m_iface->getRunDataFromDAE(values);
            m_iface->getVetoStatus(vetoStatus);
            if (check_settings)
            {
                m_iface->getDAESettingsXML(daeSettings);
                m_iface->getTCBSettingsXML(tcbSettings);
                m_iface->getHardwarePeriodsSettingsXML(hardwarePeriodsSettings);
                m_iface->getUpdateSettingsXML(updateSettings);
            }
            this_gf = m_iface->getGoodFrames();        
		    this_rf = m_iface->getRawFrames();
        }
        catch(const std::exception& ex)
        {
            std::cerr << ex.what() << std::endl;
            continue;
        }
        if (this_rf > last_rf)
        {
            m_vetopc = 100.0 * (1.0 - static_cast<double>(this_gf - last_gf) / static_cast<double>(this_rf - last_rf));
        }
        else
        {
            m_vetopc = 0.0;
        }
        last_rf = this_rf;
        last_gf = this_gf;
        setStringParam(P_RunTitle, values["RunTitle"]); 
        setStringParam(P_RBNumber, values["RBNumber"]); 
		const char* rn = values["RunNumber"];
        setStringParam(P_RunNumber, rn);
        setIntegerParam(P_IRunNumber, atol(rn));
        setStringParam(P_InstName, values["InstName"]);
        setStringParam(P_UserName, values["UserName"]);
        setStringParam(P_UserTelephone, values["UserTelephone"]);
        setStringParam(P_StartTime, values["StartTime"]);
        setDoubleParam(P_NPRatio, values["N/P Ratio"]);
        setStringParam(P_ISISCycle, values["ISISCycle"]);
        setStringParam(P_DAETimingSource, values["DAETimingSource"]);
        setStringParam(P_PeriodType, values["Period Type"]);
        
        setIntegerParam(P_RawFramesPeriod, values["RawFramesPeriod"]);
        setIntegerParam(P_GoodFramesPeriod, values["GoodFramesPeriod"]);
        
        setIntegerParam(P_RunDurationTotal, values["RunDurationTotal"]);
        setIntegerParam(P_RunDurationPeriod, values["RunDurationPeriod"]);
        setIntegerParam(P_NumTimeChannels, values["NumberOfTimeChannels"]);
        setIntegerParam(P_NumPeriods, values["NumberOfPeriods"]);
        setIntegerParam(P_DAEMemoryUsed, values["DAEMemoryUsed"]);
        
        setIntegerParam(P_Period, values["CurrentPeriod"]);
        setIntegerParam(P_NumSpectra, values["NumberOfSpectra"]);
        setIntegerParam(P_MonitorCounts, values["MonitorCounts"]);
        setIntegerParam(P_PeriodSequence, values["PeriodSequence"]);
        setIntegerParam(P_MonitorSpectrum, values["MonitorSpectrum"]);
        
        setDoubleParam(P_BeamCurrent, values["BeamCurrent"]);
        setDoubleParam(P_TotalUAmps, values["TotalUAmps"]);
        setDoubleParam(P_MonitorFrom, values["MonitorFrom"]);
        setDoubleParam(P_MonitorTo, values["MonitorTo"]);
        setDoubleParam(P_TotalDaeCounts, values["TotalDAECounts"]);
        setDoubleParam(P_CountRate, values["CountRate"]);
        setDoubleParam(P_EventModeFraction, values["EventModeCardFraction"]);
        setDoubleParam(P_VetoPC, m_vetopc);
        
        setStringParam(P_VetoStatus, vetoStatus.c_str() );
        if (check_settings) 
        {
            setStringParam(P_DAESettings, daeSettings.c_str());
		    if (compressString(tcbSettings, tcbSettingComp) == 0)
		    {
                setStringParam(P_TCBSettings, tcbSettingComp.c_str());
		    }
            setStringParam(P_HardwarePeriodsSettings, hardwarePeriodsSettings.c_str() );
            setStringParam(P_UpdateSettings, updateSettings.c_str() );
			
			std::string val;
			getDAEXML(daeSettings, "/Cluster/String[Name='Wiring Table']/Val", val);
			setStringParam(P_wiringTableFile, val.c_str());
			getDAEXML(daeSettings, "/Cluster/String[Name='Detector Table']/Val", val);
			setStringParam(P_detectorTableFile, val.c_str());
			getDAEXML(daeSettings, "/Cluster/String[Name='Spectra Table']/Val", val);
			setStringParam(P_spectraTableFile, val.c_str());
			getDAEXML(tcbSettings, "/Cluster/String[Name='Time Channel File']/Val", val);
			setStringParam(P_tcbFile, val.c_str());
			getDAEXML(hardwarePeriodsSettings, "/Cluster/String[Name='Period File']/Val", val);
			setStringParam(P_periodsFile, val.c_str());
        }          
		std::list<std::string> messages;
		std::string all_msgs;
		m_iface->getAsyncMessages(messages);
		for(std::list<std::string>::const_iterator it=messages.begin(); it != messages.end(); ++it)
		{
			std::string mess_ts;
			isisdaeInterface::stripTimeStamp(it->c_str(), mess_ts);
		    all_msgs.append(mess_ts);
			errlogSevPrintf(errlogInfo, "%s", mess_ts.c_str());
		}
		if (all_msgs.size() > 0)
		{
            setStringParam(P_AllMsgs, all_msgs.c_str());
		}
		messages.clear();
		callParamCallbacks();        
        ++counter;
	}
}	
/** Constructor for NDPluginDLL; most parameters are simply passed to NDPluginDriver::NDPluginDriver.
  * After calling the base class constructor this method sets reasonable default values for all of the
  * Transform parameters.
  * \param[in] portName The name of the asyn port driver to be created.
  * \param[in] queueSize The number of NDArrays that the input queue for this plugin can hold when
  *            NDPluginDriverBlockingCallbacks=0.  Larger queues can decrease the number of dropped arrays,
  *            at the expense of more NDArray buffers being allocated from the underlying driver's NDArrayPool.
  * \param[in] blockingCallbacks Initial setting for the NDPluginDriverBlockingCallbacks flag.
  *            0=callbacks are queued and executed by the callback thread; 1 callbacks execute in the thread
  *            of the driver doing the callbacks.
  * \param[in] NDArrayPort Name of asyn port driver for initial source of NDArray callbacks.
  * \param[in] NDArrayAddr asyn port driver address for initial source of NDArray callbacks.
  * \param[in] maxBuffers The maximum number of NDArray buffers that the NDArrayPool for this driver is
  *            allowed to allocate. Set this to -1 to allow an unlimited number of buffers.
  * \param[in] maxMemory The maximum amount of memory that the NDArrayPool for this driver is
  *            allowed to allocate. Set this to -1 to allow an unlimited amount of memory.
  * \param[in] priority The thread priority for the asyn port driver thread if ASYN_CANBLOCK is set in asynFlags.
  * \param[in] stackSize The stack size for the asyn port driver thread if ASYN_CANBLOCK is set in asynFlags.
  */
NDPluginDLL::NDPluginDLL(const char *portName, int queueSize, int blockingCallbacks,
                         const char *NDArrayPort, int NDArrayAddr, int maxBuffers, size_t maxMemory,
                         int priority, int stackSize)
    /* Invoke the base class constructor */
    : NDPluginDriver(portName, queueSize, blockingCallbacks,
                   NDArrayPort, NDArrayAddr, 1, 1024, maxBuffers, maxMemory,
                   asynInt32ArrayMask | asynFloat64ArrayMask | asynGenericPointerMask,
                   asynInt32ArrayMask | asynFloat64ArrayMask | asynGenericPointerMask,
                   ASYN_MULTIDEVICE, 1, priority, stackSize)
{
    asynStatus status;
    const char *functionName = "NDPluginDLL";
    int ii, jj;

    int dims[2];
    HMODULE hMod;
	OBJMAKER makeControllerObjects;
	int gg;
	int_string *params;





	// map the params from asyn assign param to the enumerated param in the dll.

	mapAsyn2DLL = new std::map<int,int>;
	mapDLL2Asyn = new std::map<int,int>;

 dims[0] =1024;
    dims[1] = 1024;
    this->pRaw = this->pNDArrayPool->alloc(2, dims, NDUInt16, 0, NULL);

	printf("Made NDArray, X = %i  Y = %i Type = %i \n",1024, 1024,3);

	printf("Image data pointer = %i \n", (long)(pRaw->pData));


	hMod = LoadLibrary (dll_name);
	if (NULL == hMod)
	{
		printf("Load DLL failed\n");
			exit(0);
	}

	 makeControllerObjects = (OBJMAKER) GetProcAddress (hMod, "makeControllerObjects");
	if (NULL == makeControllerObjects)
	{
		long erx=GetLastError();
		printf("Cannot get Proc Address. Error= %i\n",erx);
	}

	makeControllerObjects(
		(int*)&num_controllers,
		(genCamController*)controllers,
		(void*)madSimCallback,
		&(this->pRaw->pData));



	printf("Controllers Found: %i \n",num_controllers);


	madSimPtr=this;
			// start threads per object
//	for (int k = 0; k<num_controllers; k++)
//	{
//		Sleep(2000);
//		madSimCallback(genCamControllerEnum::make_new_thread,controllers[k]);
//	}


	//
	// get param lists from the DLL and make all params.
	//
	int asyn_param;
	int enum_param;
	int ptype;
	int nparam;

	for (int k = 0; k<num_controllers; k++)
	{
		params=controllers[k]->getCompleteParamIntStrArray();
		nparam=controllers[k]->getTotalNumParams();

		for (int pp=0;pp<nparam;pp++)
		{
			if (pp==12)
				trapHere();

			enum_param=params[pp].x;
			ptype= controllers[k]->getParamType(enum_param);

			switch(ptype)
			{

				case putGetParameters::paramInt:
					createParam(params[pp].str,asynParamInt32,&asyn_param);
					(*mapAsyn2DLL)[asyn_param] = params[pp].x;
					(*mapDLL2Asyn)[params[pp].x] = asyn_param;


					break;

				case putGetParameters::paramDouble:
					createParam(params[pp].str,asynParamFloat64,&asyn_param);
					(*mapAsyn2DLL)[asyn_param] = params[pp].x;
					(*mapDLL2Asyn)[params[pp].x] = asyn_param;
				break;

				case putGetParameters::paramString:
					createParam(params[pp].str,asynParamOctet,&asyn_param);
					(*mapAsyn2DLL)[asyn_param] = params[pp].x;
					(*mapDLL2Asyn)[params[pp].x] = asyn_param;
				break;

				case putGetParameters::paramPtr:
					createParam(params[pp].str,asynParamInt32,&asyn_param);
					(*mapAsyn2DLL)[asyn_param] = params[pp].x;
					(*mapDLL2Asyn)[params[pp].x] = asyn_param;

				break;

				default:
					printf("ERROR: NDPluginDLL::NDPluginDLL: Create Undef Param\n");
				break;


			}

		}
	// copy ALL parameters from detector to this local Area Detector object
	//so EPICS can relect what detector is doing.
	lock();
	copyParamsFromDet(0);
	callParamCallbacks();
	unlock();


	}
//    createParam(NDPluginDLLNameString,         asynParamOctet, &NDPluginDLLName);
//    createParam(NDPluginDLL1TypeString,        asynParamInt32, &NDPluginDLL1Type);

    /* Set the plugin type string */
//    setStringParam(NDPluginDriverPluginType, "NDPluginDLL");
//    setStringParam(NDPluginDLLName, "");
//    setIntegerParam(NDPluginDLL1Type, 0);


	NDArrayDataPub=NDArrayData;

    /* Try to connect to the array port */
    status = connectToArrayPort();
}
Exemple #19
0
/** Called when asyn clients call pasynInt32->write().
  * This function performs actions for some parameters, including ADAcquire,
  * ADTriggerMode, etc.
  * For all parameters it sets the value in the parameter library and calls any
  * registered callbacks..
  * \param[in] pasynUser pasynUser structure that encodes the reason and
  *            address.
  * \param[in] value Value to write. */
asynStatus hdf5Driver::writeInt32 (asynUser *pasynUser, epicsInt32 value)
{
    int function = pasynUser->reason;
    asynStatus status = asynSuccess;
    const char *functionName = "writeInt32";
    int adstatus, acquiring, imageMode;

    getIntegerParam(ADAcquire,   &acquiring);
    getIntegerParam(ADStatus,    &adstatus);
    getIntegerParam(ADImageMode, &imageMode);

    if (function == ADAcquire)
    {
        if (value && !acquiring)
        {
            setStringParam(ADStatusMessage, "Acquiring data");
            setIntegerParam(ADStatus, ADStatusAcquire);
            callParamCallbacks();
            epicsEventSignal(this->mStartEventId);
        }
        else if (!value && acquiring)
        {
            setStringParam(ADStatusMessage, "Acquisition stopped");
            if(imageMode == ADImageContinuous)
                setIntegerParam(ADStatus, ADStatusIdle);
            else
                setIntegerParam(ADStatus, ADStatusAborted);
            callParamCallbacks();
            epicsEventSignal(this->mStopEventId);
        }
    }
    else if(function == HDF5CurrentFrame)
    {
        int first, last;
        getIntegerParam(HDF5FirstFrame, &first);
        getIntegerParam(HDF5LastFrame, &last);

        if(value < first)
            value = first;
        else if(value > last)
            value = last;
    }
    else if(function < FIRST_HDF5_PARAM)
        status = ADDriver::writeInt32(pasynUser, value);

    if(status)
    {
        asynPrint(pasynUser, ASYN_TRACE_ERROR,
              "%s:%s: error, status=%d function=%d, value=%d\n",
              driverName, functionName, status, function, value);
        return status;
    }

    status = setIntegerParam(function, value);
    callParamCallbacks();

    if (status)
        asynPrint(pasynUser, ASYN_TRACE_ERROR,
              "%s:%s: error, status=%d function=%d, value=%d\n",
              driverName, functionName, status, function, value);
    else
        asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
              "%s:%s: function=%d, value=%d\n",
              driverName, functionName, function, value);

    return status;
}
/** Constructor for the shamrock class
 * \param[in] portName asyn port name to assign to the camera.
 * \param[in] shamrockID The spectrograph index.
 * \param[in] iniPath The path to the camera ini file
 * \param[in] priority The EPICS thread priority for this driver.  0=use asyn default.
 * \param[in] stackSize The size of the stack for the EPICS port thread. 0=use asyn default.
 */
shamrock::shamrock(const char *portName, int shamrockID, const char *iniPath, int priority, int stackSize)
    : asynPortDriver(portName, MAX_ADDR, NUM_SR_PARAMS, 
            asynInt32Mask | asynFloat64Mask | asynFloat32ArrayMask | asynDrvUserMask, 
            asynInt32Mask | asynFloat64Mask | asynFloat32ArrayMask,
            ASYN_CANBLOCK | ASYN_MULTIDEVICE, 1, priority, stackSize),
    shamrockId_(shamrockID)
{
    static const char *functionName = "shamrock";
    int status;
    int error;
    float minWavelength, maxWavelength;
    int numDevices;
    int numGratings;
    float pixelWidth;
    int i;

    createParam(SRWavelengthString,       asynParamFloat64,   &SRWavelength_);
    createParam(SRMinWavelengthString,    asynParamFloat64,   &SRMinWavelength_);
    createParam(SRMaxWavelengthString,    asynParamFloat64,   &SRMaxWavelength_);
    createParam(SRCalibrationString,      asynParamFloat32Array,   &SRCalibration_);
    createParam(SRGratingString,          asynParamInt32,     &SRGrating_);
    createParam(SRNumGratingsString,      asynParamInt32,     &SRNumGratings_);
    createParam(SRGratingExistsString,    asynParamInt32,     &SRGratingExists_);
    createParam(SRSlitExistsString,       asynParamInt32,     &SRSlitExists_);
    createParam(SRSlitSizeString,         asynParamFloat64,   &SRSlitSize_);

    error = ShamrockInitialize((char *)iniPath);

    status = checkError(error, functionName, "ShamrockInitialize");
    if (status) return;
    error = ShamrockGetNumberDevices(&numDevices);
    status = checkError(error, functionName, "ShamrockGetNumberDevices");
    if (status) return;
    if (numDevices < 1) {
        asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
            "%s:%s:  No Shamrock spectrographs found, numDevices=%d\n",
            driverName, functionName, numDevices);
        return;
    }
    
    // Determine the number of pixels on the attached CCD and the pixel size
    error = ShamrockGetNumberPixels(shamrockId_, &numPixels_);
    status = checkError(error, functionName, "ShamrockGetNumberPixels");
    error = ShamrockGetPixelWidth(shamrockId_, &pixelWidth);
    status = checkError(error, functionName, "ShamrockGetPixelWidth");
    calibration_ = (float *)calloc(numPixels_, sizeof(float));

    // Determine which slits are present
    for (i=0; i<MAX_SLITS; i++) {
        int present;
        error = ShamrockAutoSlitIsPresent(shamrockId_, i+1, &present);
        status = checkError(error, functionName, "ShamrockAutoSlitIsPresent");
        slitIsPresent_[i] = (present == 1);
        setIntegerParam(i, SRSlitExists_, slitIsPresent_[i]);
    }

    // Determine how many gratings are present
    error = ShamrockGetNumberGratings(shamrockId_, &numGratings);
    status = checkError(error, functionName, "ShamrockGetNumberGratings");
    setIntegerParam(SRNumGratings_, numGratings);
    // Get wavelength range of each grating
    for (i=1; i<=numGratings; i++) {
        setIntegerParam(i, SRGratingExists_, 1);
        error = ShamrockGetWavelengthLimits(shamrockId_, i, &minWavelength, &maxWavelength);
        status = checkError(error, functionName, "ShamrockGetWavelengthLimits");
        setDoubleParam(i, SRMinWavelength_, minWavelength);
        setDoubleParam(i, SRMaxWavelength_, maxWavelength);
    }
    for (i=numGratings; i<MAX_GRATINGS; i++) {
        setIntegerParam(i, SRGratingExists_, 0);
    }
    
    
    getStatus();
    
    for (i=0; i<MAX_ADDR; i++) {
        callParamCallbacks(i);
    }
    
    return;
}
Exemple #21
0
asynStatus hdf5Driver::openFile (const char *path)
{
    asynStatus status = asynSuccess;
    const char *functionName = "loadFile";

    hid_t fileId, groupId;
    H5G_info_t groupInfo;
    size_t totalFrames = 0;
    size_t maxWidth = 0, maxHeight = 0;

    // Reset some parameters
    setIntegerParam(HDF5DatasetsCount,  0);
    setIntegerParam(HDF5TotalFrames,    0);
    setIntegerParam(HDF5FirstFrame,     0);
    setIntegerParam(HDF5LastFrame,      0);
    setIntegerParam(HDF5CurrentFrame,   0);
    setIntegerParam(ADMaxSizeX,         0);
    setIntegerParam(ADMaxSizeY,         0);
    callParamCallbacks();

    // Get a file handle
    if((fileId = H5Fopen(path, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
    {
        asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
                "%s:%s couldn't open file '%s'\n",
                driverName, functionName, path);
        status = asynError;
        goto end;
    }

    // Get a handle to the '/entry' group
    if((groupId = H5Gopen2(fileId, "/entry", H5P_DEFAULT)) < 0)
    {
        asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
                "%s:%s couldn't open 'entry' group\n",
                driverName, functionName);
        status = asynError;
        goto closeFile;
    }

    // Need groupInfo to obtain number of links
    if(H5Gget_info(groupId, &groupInfo))
    {
        asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
                "%s:%s couldn't get group info\n",
                driverName, functionName);
        status = asynError;
        goto closeGroup;
    }

    // Deallocate information of previous file
    if(mpDatasets)
    {
        for(size_t i = 0; i < mDatasetsCount; ++i)
            H5Dclose(mpDatasets[i].id);
        free(mpDatasets);
    }

    // Allocate memory to store dataset information
    mpDatasets = (struct dsetInfo*) calloc(groupInfo.nlinks,
            sizeof(*mpDatasets));
    mDatasetsCount = 0;

    // Iterate over '/entry' objects
    for(size_t i = 0; i < groupInfo.nlinks; ++i)
    {
        // Get object name
        char dsetName[256];
        H5Lget_name_by_idx(groupId, ".", H5_INDEX_NAME, H5_ITER_INC, i,
                dsetName, sizeof(dsetName), H5P_DEFAULT);

        // If it doesn't start with 'data' it isn't a dataset. Ignore it.
        if(strncmp(dsetName, "data", 4))
            continue;

        // Get a handle to the dataset info structure
        struct dsetInfo *pDSet = &mpDatasets[mDatasetsCount++];
        pDSet->id = H5Dopen2(groupId, dsetName, H5P_DEFAULT);

        // Read dataset attributes
        H5LTget_attribute_int(pDSet->id, ".", "image_nr_low",
                &pDSet->imageNrLow);
        H5LTget_attribute_int(pDSet->id, ".", "image_nr_high",
                &pDSet->imageNrHigh);

        // Read dimensions (assume a 3D dataset)
        hsize_t dims[3] = {0,0,0};
        H5LTget_dataset_info(pDSet->id, ".", dims, NULL, NULL);
        totalFrames  += dims[0];
        pDSet->height = dims[1];
        pDSet->width  = dims[2];

        // Calculate maxHeight and maxWidth
        if(dims[1] > maxHeight)
            maxHeight = dims[1];

        if(dims[2] > maxWidth)
            maxWidth = dims[2];

        // Read type
        if(parseType(pDSet->id, &pDSet->type))
        {
            asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
                    "%s:%s couldn't parse dataset type\n",
                    driverName, functionName);
            status = asynError;
        }
    }

    // Update parameters
    setIntegerParam(HDF5DatasetsCount, (int) mDatasetsCount);
    setIntegerParam(HDF5TotalFrames,   (int) totalFrames);

    if(mDatasetsCount > 0)
    {
        int firstFrame = mpDatasets[0].imageNrLow;
        int lastFrame  = mpDatasets[mDatasetsCount-1].imageNrHigh;
        setIntegerParam(HDF5FirstFrame,   firstFrame);
        setIntegerParam(HDF5LastFrame,    lastFrame);
        setIntegerParam(HDF5CurrentFrame, firstFrame);
        setIntegerParam(ADMaxSizeX,       maxWidth);
        setIntegerParam(ADMaxSizeY,       maxHeight);

        int autoLoad;
        getIntegerParam(HDF5AutoLoadFrame, &autoLoad);
        if(autoLoad)
        {
            setIntegerParam(ADImageMode, ADImageSingle);
            setIntegerParam(ADNumImages, 1);
            setIntegerParam(ADAcquire,   1);
            epicsEventSignal(mStartEventId);
        }
    }

    callParamCallbacks();

closeGroup:
    H5Gclose(groupId);
closeFile:
    H5Fclose(fileId);
end:
    return status;
}
/** Callback function that is called by the NDArray driver with new NDArray data.
  * Does image statistics.
  * \param[in] pArray  The NDArray from the callback.
  */
void NDPluginStats::processCallbacks(NDArray *pArray)
{
    /* This function does array statistics.
     * It is called with the mutex already locked.  It unlocks it during long calculations when private
     * structures don't need to be protected.
     */
    NDDimension_t bgdDims[ND_ARRAY_MAX_DIMS], *pDim;
    size_t bgdPixels;
    int bgdWidth;
    int dim;
    NDStats_t stats, *pStats=&stats, statsTemp, *pStatsTemp=&statsTemp;
    double bgdCounts, avgBgd;
    NDArray *pBgdArray=NULL;
    int computeStatistics, computeCentroid, computeProfiles, computeHistogram;
    size_t sizeX=0, sizeY=0;
    int i;
    int itemp;
    int numTSPoints, currentTSPoint, TSAcquiring;
    NDArrayInfo arrayInfo;

    const char* functionName = "processCallbacks";

    /* Call the base class method */
    NDPluginDriver::processCallbacks(pArray);
    
    pArray->getInfo(&arrayInfo);
    getIntegerParam(NDPluginStatsComputeStatistics,  &computeStatistics);
    getIntegerParam(NDPluginStatsComputeCentroid,    &computeCentroid);
    getIntegerParam(NDPluginStatsComputeProfiles,    &computeProfiles);
    getIntegerParam(NDPluginStatsComputeHistogram,   &computeHistogram);
    
    if (pArray->ndims > 0) sizeX = pArray->dims[0].size;
    if (pArray->ndims == 1) sizeY = 1;
    if (pArray->ndims > 1)  sizeY = pArray->dims[1].size;

    if (sizeX != this->profileSizeX) {
        this->profileSizeX = sizeX;
        setIntegerParam(NDPluginStatsProfileSizeX,  (int)this->profileSizeX);
        for (i=0; i<MAX_PROFILE_TYPES; i++) {
            if (this->profileX[i]) free(this->profileX[i]);
            this->profileX[i] = (double *)malloc(this->profileSizeX * sizeof(double));
        }
    }
    if (sizeY != this->profileSizeY) {
        this->profileSizeY = sizeY;
        setIntegerParam(NDPluginStatsProfileSizeY,  (int)this->profileSizeY);
        for (i=0; i<MAX_PROFILE_TYPES; i++) {
            if (this->profileY[i]) free(this->profileY[i]);
            this->profileY[i] = (double *)malloc(this->profileSizeY * sizeof(double));
        }
    }

    if (computeStatistics) {
        getIntegerParam(NDPluginStatsBgdWidth,           &bgdWidth);
        doComputeStatistics(pArray, pStats);
        /* If there is a non-zero background width then compute the background counts */
        if (bgdWidth > 0) {
            bgdPixels = 0;
            bgdCounts = 0.;
            /* Initialize the dimensions of the background array */
            for (dim=0; dim<pArray->ndims; dim++) {
                pArray->initDimension(&bgdDims[dim], pArray->dims[dim].size);
            }
            for (dim=0; dim<pArray->ndims; dim++) {
                pDim = &bgdDims[dim];
                pDim->offset = 0;
                pDim->size = MIN((size_t)bgdWidth, pDim->size);
                this->pNDArrayPool->convert(pArray, &pBgdArray, pArray->dataType, bgdDims);
                pDim->size = pArray->dims[dim].size;
                if (!pBgdArray) {
                    asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
                        "%s::%s, error allocating array buffer in convert\n",
                        driverName, functionName);
                    continue;
                }
                doComputeStatistics(pBgdArray, pStatsTemp);
                pBgdArray->release();
                bgdPixels += pStatsTemp->nElements;
                bgdCounts += pStatsTemp->total;
                pDim->offset = MAX(0, pDim->size - 1 - bgdWidth);
                pDim->size = MIN((size_t)bgdWidth, pArray->dims[dim].size - pDim->offset);
                this->pNDArrayPool->convert(pArray, &pBgdArray, pArray->dataType, bgdDims);
                pDim->offset = 0;
                pDim->size = pArray->dims[dim].size;
                if (!pBgdArray) {
                    asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
                        "%s::%s, error allocating array buffer in convert\n",
                        driverName, functionName);
                    continue;
                }
                doComputeStatistics(pBgdArray, pStatsTemp);
                pBgdArray->release();
                bgdPixels += pStatsTemp->nElements;
                bgdCounts += pStatsTemp->total;
            }
            if (bgdPixels < 1) bgdPixels = 1;
            avgBgd = bgdCounts / bgdPixels;
            pStats->net = pStats->total - avgBgd*pStats->nElements;
        }
        setDoubleParam(NDPluginStatsMinValue,    pStats->min);
        setDoubleParam(NDPluginStatsMinX,        (double)pStats->minX);
        setDoubleParam(NDPluginStatsMinY,        (double)pStats->minY);                        
        setDoubleParam(NDPluginStatsMaxValue,    pStats->max);
        setDoubleParam(NDPluginStatsMaxX,        (double)pStats->maxX);
        setDoubleParam(NDPluginStatsMaxY,        (double)pStats->maxY);                                
        setDoubleParam(NDPluginStatsMeanValue,   pStats->mean);
        setDoubleParam(NDPluginStatsSigmaValue,  pStats->sigma);
        setDoubleParam(NDPluginStatsTotal,       pStats->total);
        setDoubleParam(NDPluginStatsNet,         pStats->net);
        asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER,
            (char *)pArray->pData, arrayInfo.totalBytes,
            "%s:%s min=%f, max=%f, mean=%f, total=%f, net=%f",
            driverName, functionName, pStats->min, pStats->max, pStats->mean, pStats->total, pStats->net);
    }

    if (computeCentroid) {
        doComputeCentroid(pArray);
        setDoubleParam(NDPluginStatsCentroidX,   this->centroidX);
        setDoubleParam(NDPluginStatsCentroidY,   this->centroidY);
        setDoubleParam(NDPluginStatsSigmaX,      this->sigmaX);
        setDoubleParam(NDPluginStatsSigmaY,      this->sigmaY);
        setDoubleParam(NDPluginStatsSigmaXY,     this->sigmaXY);
    }
         
    if (computeProfiles) {
        doComputeProfiles(pArray);
    }
    
    if (computeHistogram) {
        getIntegerParam(NDPluginStatsHistSize, &itemp); this->histSizeNew = itemp;
        getDoubleParam (NDPluginStatsHistMin,  &this->histMin);
        getDoubleParam (NDPluginStatsHistMax,  &this->histMax);
        doComputeHistogram(pArray);
        setDoubleParam(NDPluginStatsHistEntropy, this->histEntropy);
        doCallbacksFloat64Array(this->histogram, this->histogramSize, NDPluginStatsHistArray, 0);
    }
    
    getIntegerParam(NDPluginStatsTSCurrentPoint,     &currentTSPoint);
    getIntegerParam(NDPluginStatsTSNumPoints,        &numTSPoints);
    getIntegerParam(NDPluginStatsTSAcquiring,        &TSAcquiring);
    if (TSAcquiring) {
        timeSeries[TSMinValue][currentTSPoint]    = pStats->min;
        timeSeries[TSMinX][currentTSPoint]        = (double)pStats->minX;
        timeSeries[TSMinY][currentTSPoint]        = (double)pStats->minY;                        
        timeSeries[TSMaxValue][currentTSPoint]    = pStats->max;
        timeSeries[TSMaxX][currentTSPoint]        = (double)pStats->maxX;
        timeSeries[TSMaxY][currentTSPoint]        = (double)pStats->maxY;                                
        timeSeries[TSMeanValue][currentTSPoint]   = pStats->mean;
        timeSeries[TSSigmaValue][currentTSPoint]  = pStats->sigma;
        timeSeries[TSTotal][currentTSPoint]       = pStats->total;
        timeSeries[TSNet][currentTSPoint]         = pStats->net;
        timeSeries[TSCentroidX][currentTSPoint] = this->centroidX;
        timeSeries[TSCentroidY][currentTSPoint] = this->centroidY;
        timeSeries[TSSigmaX][currentTSPoint]    = this->sigmaX;
        timeSeries[TSSigmaY][currentTSPoint]    = this->sigmaY;
        timeSeries[TSSigmaXY][currentTSPoint]   = this->sigmaXY;
        currentTSPoint++;
        setIntegerParam(NDPluginStatsTSCurrentPoint, currentTSPoint);
        if (currentTSPoint >= numTSPoints) {
            setIntegerParam(NDPluginStatsTSAcquiring, 0);
            doTimeSeriesCallbacks();
        }
    }
            
    /* Save a copy of this array for calculations when cursor is moved or threshold is changed */
    if (this->pArrays[0]) this->pArrays[0]->release();
    this->pArrays[0] = this->pNDArrayPool->copy(pArray, NULL, 1);

    callParamCallbacks();
}
Exemple #23
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);
}
/** Called when asyn clients call pasynInt32->write().
  * This function performs actions for some parameters.
  * For all parameters it sets the value in the parameter library and calls any registered callbacks..
  * \param[in] pasynUser pasynUser structure that encodes the reason and address.
  * \param[in] value Value to write. */
asynStatus NDPluginStats::writeInt32(asynUser *pasynUser, epicsInt32 value)
{
    int function = pasynUser->reason;
    asynStatus status = asynSuccess;
    int i;
    int numPoints, currentPoint;
    static const char *functionName = "writeInt32";


    /* Set the parameter in the parameter library. */
    status = (asynStatus) setIntegerParam(function, value);

    if (function == NDPluginStatsCursorX) {
        this->cursorX = value;
        if (this->pArrays[0]) {
            doComputeProfiles(this->pArrays[0]);
        }
    } else if (function == NDPluginStatsCursorY) {
        this->cursorY = value;
        if (this->pArrays[0]) {
            doComputeProfiles(this->pArrays[0]);
        }
    } else if (function == NDPluginStatsTSNumPoints) {
        for (i=0; i<MAX_TIME_SERIES_TYPES; i++) {
            free(this->timeSeries[i]);
            timeSeries[i] = (double *)calloc(value, sizeof(double));
        }
    } else if (function == NDPluginStatsTSControl) {
        switch (value) {
            case TSEraseStart:
                setIntegerParam(NDPluginStatsTSCurrentPoint, 0);
                setIntegerParam(NDPluginStatsTSAcquiring, 1);
                getIntegerParam(NDPluginStatsTSNumPoints, &numPoints);
                for (i=0; i<MAX_TIME_SERIES_TYPES; i++) {
                    memset(this->timeSeries[i], 0, numPoints*sizeof(double));
                }
                break;
            case TSStart:
                getIntegerParam(NDPluginStatsTSNumPoints, &numPoints);
                getIntegerParam(NDPluginStatsTSCurrentPoint, &currentPoint);
                if (currentPoint < numPoints) {
                    setIntegerParam(NDPluginStatsTSAcquiring, 1);
                }
                break;
            case TSStop:
                setIntegerParam(NDPluginStatsTSAcquiring, 0);
                doTimeSeriesCallbacks();
                break;
            case TSRead:
                doTimeSeriesCallbacks();
                break;
        }
    } else {
        /* If this parameter belongs to a base class call its method */
        if (function < FIRST_NDPLUGIN_STATS_PARAM) 
            status = NDPluginDriver::writeInt32(pasynUser, value);
    }
    
    /* Do callbacks so higher layers see any changes */
    status = (asynStatus) callParamCallbacks();
    
    if (status) 
        epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize, 
                  "%s:%s: status=%d, function=%d, value=%d", 
                  driverName, functionName, status, function, value);
    else        
        asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, 
              "%s:%s: function=%d, value=%d\n", 
              driverName, functionName, function, value);
    return status;
}
Exemple #25
0
/** Called when asyn clients call pasynInt32->write().
  * \param[in] pasynUser pasynUser structure that encodes the reason and address.
  * \param[in] value Value to write. */
asynStatus drvQuadEM::writeInt32(asynUser *pasynUser, epicsInt32 value)
{
    int function = pasynUser->reason;
    int status = asynSuccess;
    int channel;
    const char *paramName;
    const char* functionName = "writeInt32";

    getAddress(pasynUser, &channel);
    
    /* Set the parameter in the parameter library. */
    status |= setIntegerParam(channel, function, value);
    
    /* Fetch the parameter string name for possible use in debugging */
    getParamName(function, &paramName);

    if (function == P_Acquire) {
        if (value) {
            epicsRingBytesFlush(ringBuffer_);
            ringCount_ = 0;
        }
        status |= setAcquire(value);
    } 
    else if (function == P_AcquireMode) {
        if (value != QEAcquireModeContinuous) {
            status |= setAcquire(0);
            setIntegerParam(P_Acquire, 0);
        } 
        status |= setAcquireMode(value);
        status |= readStatus();
    }
    else if (function == P_BiasState) {
        status |= setBiasState(value);
        status |= readStatus();
    }
    else if (function == P_BiasInterlock) {
        status |= setBiasInterlock(value);
        status |= readStatus();
    }
    else if (function == P_NumChannels) {
        status |= setNumChannels(value);
        status |= readStatus();
    }
    else if (function == P_NumAcquire) {
        status |= setNumAcquire(value);
        status |= readStatus();
    }
    else if (function == P_PingPong) {
        status |= setPingPong(value);
        status |= readStatus();
    }
    else if (function == P_Range) {
        status |= setRange(value);
        status |= readStatus();
    }
    else if (function == P_ReadData) {
        status |= doDataCallbacks();
    }
    else if (function == P_Resolution) {
        status |= setResolution(value);
        status |= readStatus();
    }
    else if (function == P_TriggerMode) {
        status |= setTriggerMode(value);
        status |= readStatus();
    }
    else if (function == P_ValuesPerRead) {
        valuesPerRead_ = value;
        status |= setValuesPerRead(value);
        status |= readStatus();
    }
    else if (function == P_ReadFormat) {
        status |= setReadFormat(value);
        status |= readStatus();
    }
    else if (function == P_ReadStatus) {
        // We don't do this if we are acquiring, too disruptive
        if (!acquiring_) {
            status |= readStatus();
        }
    }
    else if (function == P_Reset) {
        status |= reset();
        status |= readStatus();
    }
    else {
        /* All other parameters just get set in parameter list, no need to
         * act on them here */
    }
    
    /* Do callbacks so higher layers see any changes */
    status |= (asynStatus) callParamCallbacks();
    
    if (status) 
        epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize, 
                  "%s:%s: status=%d, function=%d, name=%s, value=%d", 
                  driverName, functionName, status, function, paramName, value);
    else        
        asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, 
              "%s:%s: function=%d, name=%s, value=%d\n", 
              driverName, functionName, function, paramName, value);
    return (asynStatus)status;
}
/** Base method for writing a file
  * Handles logic for NDFileModeSingle, NDFileModeCapture and NDFileModeStream when the derived class does or
  * does not support NDPulginFileMultiple. Calls writeFile in the derived class. */
asynStatus NDPluginFile::writeFileBase() 
{
    int status = asynSuccess;
    int fileWriteMode;
    int numCapture, numCaptured;
    int i;
    int deleteDriverFile;
    NDArray *pArray;
    NDAttribute *pAttribute;
    char driverFileName[MAX_FILENAME_LEN];
    char errorMessage[256];
    const char* functionName = "writeFileBase";

    /* Make sure there is a valid array */
    if (!this->pArrays[0]) {
        asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
            "%s:%s: ERROR, must collect an array to get dimensions first\n",
            driverName, functionName);
        return(asynError);
    }
    
    getIntegerParam(NDFileWriteMode, &fileWriteMode);    
    getIntegerParam(NDFileNumCapture, &numCapture);    
    getIntegerParam(NDFileNumCaptured, &numCaptured);

    setIntegerParam(NDFileWriteStatus, NDFileWriteOK);
    setStringParam(NDFileWriteMessage, "");
    
    /* We unlock the overall mutex here because we want the callbacks to be able to queue new
     * frames without waiting while we write files here.  The only restriction is that the
     * callbacks must not modify any part of the class structure that we use here. */

    switch(fileWriteMode) {
        case NDFileModeSingle:
            setIntegerParam(NDWriteFile, 1);
            callParamCallbacks();
            status = this->openFileBase(NDFileModeWrite, this->pArrays[0]);
            if (status == asynSuccess) {
                this->unlock();
                epicsMutexLock(this->fileMutexId);
                status = this->writeFile(this->pArrays[0]);
                epicsMutexUnlock(this->fileMutexId);
                this->lock();
                if (status) {
                    epicsSnprintf(errorMessage, sizeof(errorMessage)-1, 
                        "Error writing file, status=%d", status);
                    asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
                          "%s:%s %s\n", 
                          driverName, functionName, errorMessage);
                    setIntegerParam(NDFileWriteStatus, NDFileWriteError);
                    setStringParam(NDFileWriteMessage, errorMessage);
                } else {
                    status = this->closeFileBase(); 
                }
            }
            setIntegerParam(NDWriteFile, 0);
            callParamCallbacks();
            break;
        case NDFileModeCapture:
            /* Write the file */
            if (!this->pCapture) {
                asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
                    "%s:%s: ERROR, no capture buffer present\n", 
                    driverName, functionName);
                setIntegerParam(NDFileWriteStatus, NDFileWriteError);
                setStringParam(NDFileWriteMessage, "ERROR, no capture buffer present");
                break;
            }
            setIntegerParam(NDWriteFile, 1);
            callParamCallbacks();
            if (this->supportsMultipleArrays)
                status = this->openFileBase(NDFileModeWrite | NDFileModeMultiple, this->pArrays[0]);
            if (status == asynSuccess) {
                for (i=0; i<numCaptured; i++) {
                    pArray = this->pCapture[i];
                    if (!this->supportsMultipleArrays)
                        status = this->openFileBase(NDFileModeWrite, pArray);
                    if (status == asynSuccess) {
                        this->unlock();
                        epicsMutexLock(this->fileMutexId);
                        status = this->writeFile(pArray);
                        epicsMutexUnlock(this->fileMutexId);
                        this->lock();
                        if (status) {
                            epicsSnprintf(errorMessage, sizeof(errorMessage)-1, 
                                "Error writing file, status=%d", status);
                            asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
                                  "%s:%s %s\n", 
                                  driverName, functionName, errorMessage);
                            setIntegerParam(NDFileWriteStatus, NDFileWriteError);
                            setStringParam(NDFileWriteMessage, errorMessage);
                        } else {
                            if (!this->supportsMultipleArrays)
                                status = this->closeFileBase();
                        }
                    }
                }
            }
            freeCaptureBuffer(numCapture);
            if ((status == asynSuccess) && this->supportsMultipleArrays) 
                status = this->closeFileBase();
            setIntegerParam(NDFileNumCaptured, 0);
            setIntegerParam(NDWriteFile, 0);
            callParamCallbacks();
            break;
        case NDFileModeStream:
            if (!this->supportsMultipleArrays)
                status = this->openFileBase(NDFileModeWrite | NDFileModeMultiple, this->pArrays[0]);
            if (status == asynSuccess) {
                this->unlock();
                epicsMutexLock(this->fileMutexId);
                status = this->writeFile(this->pArrays[0]);
                epicsMutexUnlock(this->fileMutexId);
                this->lock();
                if (status) {
                    epicsSnprintf(errorMessage, sizeof(errorMessage)-1, 
                        "Error writing file, status=%d", status);
                    asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
                          "%s:%s %s\n", 
                          driverName, functionName, errorMessage);
                    setIntegerParam(NDFileWriteStatus, NDFileWriteError);
                    setStringParam(NDFileWriteMessage, errorMessage);
                } else {
                    if (!this->supportsMultipleArrays)
                        status = this->closeFileBase();
                }
            }
            break;
        default:
            asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
                "%s:%s: ERROR, unknown fileWriteMode %d\n", 
                driverName, functionName, fileWriteMode);
            break;
    }
    
    /* Check to see if we should delete the original file
     * Only do this if all of the following conditions are met
     *  - DeleteOriginalFile is true
     *  - There were no errors above
     *  - The NDFullFileName attribute is present and contains a non-blank string
     */
    getIntegerParam(NDFileDeleteDriverFile, &deleteDriverFile);
    if ((status == asynSuccess) && deleteDriverFile) {
        pAttribute = this->pArrays[0]->pAttributeList->find("DriverFileName");
        if (pAttribute) {
            status = pAttribute->getValue(NDAttrString, driverFileName, sizeof(driverFileName));
            if ((status == asynSuccess) && (strlen(driverFileName) > 0)) {
                status = remove(driverFileName);
                if (status != 0) {
                    asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
                              "%s:%s: error deleting file %s, error=%s\n",
                              driverName, functionName, driverFileName, strerror(errno));
                }
            }
        }
    }
    
    return((asynStatus)status);
}
Exemple #27
0
/** Callback function that is called by the NDArray driver with new NDArray data.
  * If the plugin is running then it attaches position data to the NDArray as NDAttributes
  * and then passes the array on.  If the plugin is not running then NDArrays are not
  * passed through to the next plugin(s) in the chain.
  * \param[in] pArray  The NDArray from the callback.
  */ 
void NDPosPlugin::processCallbacks(NDArray *pArray)
{
  int index = 0;
  int running = NDPOS_IDLE;
  int skip = 0;
  int mode = 0;
  int size = 0;
  int duplicates = 0;
  int dropped = 0;
  int expectedID = 0;
  int IDDifference = 0;
  epicsInt32 IDValue = 0;
  char IDName[MAX_STRING_SIZE];
  static const char *functionName = "NDPosPlugin::processCallbacks";

  // Call the base class method
  NDPluginDriver::processCallbacks(pArray);
  getIntegerParam(NDPos_Running, &running);
  // We must maintain the size of the list ourselves, as calling
  // size() on the list has a complexity of O(n) which causes a problem
  // once we get into tens of thousands of items.
  getIntegerParam(NDPos_CurrentQty, &size);
  // Only attach the position data to the array if we are running
  if (running == NDPOS_RUNNING){
    getIntegerParam(NDPos_CurrentIndex, &index);
    if (index >= size){
      // We've reached the end of our positions, stop to make sure we don't overflow
      setIntegerParam(NDPos_Running, NDPOS_IDLE);
      running = NDPOS_IDLE;
    } else {
      // Read the ID parameter from the NDArray.  If it cannot be found then abort
      getStringParam(NDPos_IDName, MAX_STRING_SIZE, IDName);
      // Check for IDName, if it is empty the we use the unique ID of the array
      if (strcmp(IDName, "") == 0){
        IDValue = pArray->uniqueId;
      } else {
        NDAttribute *IDAtt = pArray->pAttributeList->find(IDName);
        if (IDAtt){
          epicsInt32 IDValue;
          if (IDAtt->getValue(NDAttrInt32, &IDValue, sizeof(epicsInt32)) == ND_ERROR){
            // Error, unable to get the value from the ID attribute
            asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
                      "%s::%s ERROR: could not retrieve expected ID from attribute [%s]\n",
                      driverName, functionName, IDName);
            setIntegerParam(NDPos_Running, NDPOS_IDLE);
            running = NDPOS_IDLE;
          }
        } else {
          // Error, unable to find the named ID attribute
          asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
                    "%s::%s ERROR: could not find attribute [%s]\n",
                    driverName, functionName, IDName);
          setIntegerParam(NDPos_Running, NDPOS_IDLE);
          running = NDPOS_IDLE;
        }
      }
      if (running == NDPOS_RUNNING){
        // Check the ID is the same as the expected index
        getIntegerParam(NDPos_IDDifference, &IDDifference);
        getIntegerParam(NDPos_ExpectedID, &expectedID);
        if (expectedID < IDValue){
          asynPrint(this->pasynUserSelf, ASYN_TRACE_WARNING,
                    "%s::%s WARNING: possible frame drop detected: expected ID [%d] received ID [%d]\n",
                    driverName, functionName, expectedID, IDValue);
          // If expected is less than ID throw away positions and record dropped events
          getIntegerParam(NDPos_MissingFrames, &dropped);
          getIntegerParam(NDPos_Mode, &mode);
          if (mode == MODE_DISCARD){
            while ((expectedID < IDValue) && (size > 0)){
              // The index will stay the same, and we need to pop the value out of the position array
              positionArray.erase(positionArray.begin());
              size--;
              expectedID += IDDifference;
              dropped++;
            }
            // If the size has dropped to zero then we've run out of positions, abort
            if (size == 0){
              setIntegerParam(NDPos_Running, NDPOS_IDLE);
              running = NDPOS_IDLE;
            }
            setIntegerParam(NDPos_CurrentQty, size);
          } else if (mode == MODE_KEEP){
            while (expectedID < IDValue && (index < size)){
              index++;
              expectedID += IDDifference;
              dropped++;
            }
            // If the index has reached the size of the array then we've run out of positions, abort
            if (index == size){
              setIntegerParam(NDPos_Running, NDPOS_IDLE);
              running = NDPOS_IDLE;
            }
            setIntegerParam(NDPos_CurrentIndex, index);
          }
          setIntegerParam(NDPos_ExpectedID, expectedID);
          setIntegerParam(NDPos_MissingFrames, dropped);
        } else if (expectedID > IDValue){
          asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
                    "%s::%s ERROR: dropping frame! possible duplicate detected: expected ID [%d] received ID [%d]\n",
                    driverName, functionName, expectedID, IDValue);
          // If expected is greater than ID then ignore the frame and record duplicate event
          getIntegerParam(NDPos_DuplicateFrames, &duplicates);
          duplicates++;
          setIntegerParam(NDPos_DuplicateFrames, duplicates);
          skip = 1;
        }
      }

      // Only perform the actual setting of positions if we aren't skipping
      if (skip == 0 && running == NDPOS_RUNNING){
        // We always keep the last array so read() can use it.
        // Release previous one. Reserve new one below during the copy.
        if (this->pArrays[0]){
          this->pArrays[0]->release();
          this->pArrays[0] = NULL;
        }
        // We must make a copy of the array as we are going to alter it
        this->pArrays[0] = this->pNDArrayPool->copy(pArray, this->pArrays[0], 1);
        if (this->pArrays[0]){
          std::list<std::map<std::string, double> >::iterator it = positionArray.begin();
          std::advance(it, index);
          //std::map<std::string, double> pos = positionArray[index];
          std::map<std::string, double> pos = *it;
          std::stringstream sspos;
          sspos << "[";
          bool firstTime = true;
          std::map<std::string, double>::iterator iter;
          for (iter = pos.begin(); iter != pos.end(); iter++){
            if (firstTime){
              firstTime = false;
            } else {
              sspos << ",";
            }
            sspos << iter->first << "=" << iter->second;
            // Create the NDAttribute with the position data
            NDAttribute *pAtt = new NDAttribute(iter->first.c_str(), "Position of NDArray", NDAttrSourceDriver, driverName, NDAttrFloat64, &(iter->second));
            // Add the NDAttribute to the NDArray
            this->pArrays[0]->pAttributeList->add(pAtt);
          }
          sspos << "]";
          setStringParam(NDPos_CurrentPos, sspos.str().c_str());

        } else {
          // We were unable to allocate the required buffer (memory or qty exceeded).
          // This results in us dropping a frame, note it and print an error
          asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
                    "%s::%s ERROR: dropped frame! Could not allocate the required buffer\n",
                    driverName, functionName);
          // Note the frame drop
          getIntegerParam(NDPluginDriverDroppedArrays, &dropped);
          dropped++;
          setIntegerParam(NDPluginDriverDroppedArrays, dropped);
          skip = 1;
        }

        // Check the mode
        getIntegerParam(NDPos_Mode, &mode);
        if (mode == MODE_DISCARD){
          // The index will stay the same, and we need to pop the value out of the position array
          positionArray.erase(positionArray.begin());
          size--;
          setIntegerParam(NDPos_CurrentQty, size);
        } else if (mode == MODE_KEEP){
          index++;
          setIntegerParam(NDPos_CurrentIndex, index);
        }
        // Increment the expectedID by the difference
        expectedID += IDDifference;
        setIntegerParam(NDPos_ExpectedID, expectedID);
      }
    }
    // If the size has dropped to zero then we've run out of positions, abort
    if (size == 0){
      setIntegerParam(NDPos_Running, NDPOS_IDLE);
    }
    callParamCallbacks();
    if (skip == 0 && running == NDPOS_RUNNING){
      this->unlock();
      doCallbacksGenericPointer(this->pArrays[0], NDArrayData, 0);
      this->lock();
    }
  }
}
/** Callback function that is called by the NDArray driver with new NDArray data.
  * Saves a single file if NDFileWriteMode=NDFileModeSingle and NDAutoSave=1.
  * Stores array in a capture buffer if NDFileWriteMode=NDFileModeCapture and NDFileCapture=1.
  * Appends data to an open file if NDFileWriteMode=NDFileModeStream and NDFileCapture=1.
  * In capture or stream mode if the desired number of arrays has been saved (NDFileNumCaptured=NDFileNumCapture)
  * then it stops capture or streaming.
  * \param[in] pArray  The NDArray from the callback.
  */ 
void NDPluginFile::processCallbacks(NDArray *pArray)
{
    int fileWriteMode, autoSave, capture;
    int arrayCounter;
    int numCapture, numCaptured;
    //const char* functionName = "processCallbacks";

    /* First check if the callback is really for this file saving plugin */
    if (!this->attrIsProcessingRequired(pArray->pAttributeList))
        return;

    /* Most plugins want to increment the arrayCounter each time they are called, which NDPluginDriver
     * does.  However, for this plugin we only want to increment it when we actually got a callback we were
     * supposed to save.  So we save the array counter before calling base method, increment it here */
    getIntegerParam(NDArrayCounter, &arrayCounter);

    /* Call the base class method */
    NDPluginDriver::processCallbacks(pArray);
    
    getIntegerParam(NDAutoSave, &autoSave);
    getIntegerParam(NDFileCapture, &capture);    
    getIntegerParam(NDFileWriteMode, &fileWriteMode);    
    getIntegerParam(NDFileNumCapture, &numCapture);    
    getIntegerParam(NDFileNumCaptured, &numCaptured);

    /* We always keep the last array so read() can use it.  
     * Release previous one, reserve new one */
    if (this->pArrays[0]) this->pArrays[0]->release();
    pArray->reserve();
    this->pArrays[0] = pArray;
    
    switch(fileWriteMode) {
        case NDFileModeSingle:
            if (autoSave) {
                arrayCounter++;
                writeFileBase();
            }
            break;
        case NDFileModeCapture:
            if (capture) {
                if (numCaptured < numCapture) {
                    this->pNDArrayPool->copy(pArray, this->pCapture[numCaptured++], 1);
                    arrayCounter++;
                    setIntegerParam(NDFileNumCaptured, numCaptured);
                } 
                if (numCaptured == numCapture) {
                    if (autoSave) {
                        writeFileBase();
                    }
                    capture = 0;
                    setIntegerParam(NDFileCapture, capture);
                }
            }
            break;
        case NDFileModeStream:
            if (capture) {
                numCaptured++;
                arrayCounter++;
                setIntegerParam(NDFileNumCaptured, numCaptured);
                writeFileBase();
                if (numCaptured == numCapture) {
                    doCapture(0);
                }
            }
            break;
    }

    /* Update the parameters.  */
    setIntegerParam(NDArrayCounter, arrayCounter);
    callParamCallbacks();
}
Exemple #29
0
/**
 * Readout thread function
 */
void ADSBIG::readoutTask(void)
{
  epicsEventWaitStatus eventStatus;
  epicsFloat64 timeout = 0.001;
  bool error = false;
  size_t dims[2];
  int nDims = 2;
  epicsInt32 sizeX = 0;
  epicsInt32 sizeY = 0;
  epicsInt32 minX = 0;
  epicsInt32 minY = 0;
  NDDataType_t dataType;
  epicsInt32 iDataType = 0;
  epicsUInt32 dataSize = 0;
  epicsTimeStamp nowTime;
  NDArray *pArray = NULL;
  epicsInt32 numImagesCounter = 0;
  epicsInt32 imageCounter = 0;
  PAR_ERROR cam_err = CE_NO_ERROR;

  const char* functionName = "ADSBIG::readoutTask";
  asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s Started Readout Thread.\n", functionName);

  while (1) {

    //Wait for a stop event, with a short timeout, to catch any that were done after last one.
    eventStatus = epicsEventWaitWithTimeout(m_stopEvent, timeout);          
    if (eventStatus == epicsEventWaitOK) {
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s Got Stop Event Before Start Event.\n", functionName);
    }

    lock();
    if (!error) {
      setStringParam(ADStatusMessage, "Idle");
    }
    callParamCallbacks();
    unlock();

    eventStatus = epicsEventWait(m_startEvent);          
    if (eventStatus == epicsEventWaitOK) {
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s Got Start Event.\n", functionName);
      error = false;
      setStringParam(ADStatusMessage, " ");
      lock();
      setIntegerParam(ADNumImagesCounter, 0);
      setIntegerParam(ADNumExposuresCounter, 0);

      //Sanity checks
      if ((p_Cam == NULL) || (p_Img == NULL)) {
        asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s NULL pointer.\n", functionName);
        break;
      }

      //printf("%s Time before acqusition: ", functionName);
      //epicsTime::getCurrent().show(0);

      //Read the frame sizes 
      getIntegerParam(ADMinX, &minX);
      getIntegerParam(ADMinY, &minY);
      getIntegerParam(ADSizeX, &sizeX);
      getIntegerParam(ADSizeY, &sizeY);
      p_Cam->SetSubFrame(minX, minY, sizeX, sizeY);

      //Read what type of image we want - light field or dark field?
      int darkField = 0;
      getIntegerParam(ADSBIGDarkFieldParam, &darkField);

      if (darkField > 0) {
        cam_err = p_Cam->GrabSetup(p_Img, SBDF_DARK_ONLY);
      } else {
        cam_err = p_Cam->GrabSetup(p_Img, SBDF_LIGHT_ONLY);
      }
      if (cam_err != CE_NO_ERROR) {
        asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
                "%s. CSBIGCam::GrabSetup returned an error. %s\n", 
              functionName, p_Cam->GetErrorString(cam_err).c_str());
        error = true;
        setStringParam(ADStatusMessage, p_Cam->GetErrorString(cam_err).c_str());
      } 

      unsigned short binX = 0;
      unsigned short binY = 0;
      p_Img->GetBinning(binX, binY);
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, " binX: %d\n", binY);
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, " binY: %d\n", binX);
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, " PixelHeight: %f\n", p_Img->GetPixelHeight());
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, " PixelWidth: %f\n", p_Img->GetPixelWidth());
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, " Height: %d\n", p_Img->GetHeight());
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, " Width: %d\n", p_Img->GetWidth());
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, " Readout Mode: %d\n", p_Cam->GetReadoutMode());
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, " Dark Field: %d\n", darkField);

      if (!error) {

        //Do exposure
        callParamCallbacks();
        unlock();
        if (darkField > 0) {
          cam_err = p_Cam->GrabMain(p_Img, SBDF_DARK_ONLY);
        } else {
          cam_err = p_Cam->GrabMain(p_Img, SBDF_LIGHT_ONLY);
        }
        lock();
        if (cam_err != CE_NO_ERROR) {
          asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
                    "%s. CSBIGCam::GrabMain returned an error. %s\n", 
                    functionName, p_Cam->GetErrorString(cam_err).c_str());
          error = true;
          setStringParam(ADStatusMessage, p_Cam->GetErrorString(cam_err).c_str());
        }

        setDoubleParam(ADSBIGPercentCompleteParam, 100.0);

        if (!m_aborted) { 
        
        unsigned short *pData = p_Img->GetImagePointer();
        
        //printf("%s Time after acqusition: ", functionName);
        //epicsTime::getCurrent().show(0);

        //Update counters
        getIntegerParam(NDArrayCounter, &imageCounter);
        imageCounter++;
        setIntegerParam(NDArrayCounter, imageCounter);
        getIntegerParam(ADNumImagesCounter, &numImagesCounter);
        numImagesCounter++;
        setIntegerParam(ADNumImagesCounter, numImagesCounter);

        //NDArray callbacks
        int arrayCallbacks = 0;
        getIntegerParam(NDArrayCallbacks, &arrayCallbacks);
        getIntegerParam(NDDataType, &iDataType);
        dataType = static_cast<NDDataType_t>(iDataType);
        if (dataType == NDUInt8) {
          dataSize = sizeX*sizeY*sizeof(epicsUInt8);
        } else if (dataType == NDUInt16) {
          dataSize = sizeX*sizeY*sizeof(epicsUInt16);
        } else if (dataType == NDUInt32) {
          dataSize = sizeX*sizeY*sizeof(epicsUInt32);
        } else {
          asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
                    "%s. ERROR: We can't handle this data type. dataType: %d\n", 
                    functionName, dataType);
          error = true;
          dataSize = 0;
        }
        setIntegerParam(NDArraySize, dataSize);
        
        if (!error) {
          
          if (arrayCallbacks) {
            //Allocate an NDArray
            dims[0] = sizeX;
            dims[1] = sizeY;
            if ((pArray = this->pNDArrayPool->alloc(nDims, dims, dataType, 0, NULL)) == NULL) {
              asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
                        "%s. ERROR: pArray is NULL.\n", 
                        functionName);
            } else {
              epicsTimeGetCurrent(&nowTime);
              pArray->uniqueId = imageCounter;
              pArray->timeStamp = nowTime.secPastEpoch + nowTime.nsec / 1.e9;
              updateTimeStamp(&pArray->epicsTS);
              //Get any attributes that have been defined for this driver
              this->getAttributes(pArray->pAttributeList);
              //We copy data because the SBIG class library holds onto the original buffer until the next acqusition
              asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, 
                        "%s: Copying data. dataSize: %d\n", functionName, dataSize);
              memcpy(pArray->pData, pData, dataSize);
                
              unlock();
              asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s: Calling NDArray callback\n", functionName);
              doCallbacksGenericPointer(pArray, NDArrayData, 0);
              lock();
              pArray->release();
            }
            
          }
          
          setIntegerParam(ADStatus, ADStatusIdle);
          
        } else {
          setIntegerParam(ADStatus, ADStatusError);
        }

        } else { //end if (!m_aborted)
          setIntegerParam(ADStatus, ADStatusAborted);
          m_aborted = false;
        }
        
      }
      
      callParamCallbacks();
      //Complete Acquire callback
      setIntegerParam(ADAcquire, 0);
      callParamCallbacks();
      unlock();

      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, 
                "%s Completed acqusition.\n", functionName);

    } //end of start event

  } //end of while(1)

  asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
            "%s: ERROR: Exiting ADSBIGReadoutTask main loop.\n", functionName);

}
Exemple #30
0
/** Constructor for mythen driver; most parameters are simply passed to ADDriver::ADDriver.
  * After calling the base class constructor this method creates a thread to collect the detector data, 
  * and sets reasonable default values for the parameters defined in this class, asynNDArrayDriver, and ADDriver.
  * \param[in] portName The name of the asyn port driver to be created.
  * \param[in] IPPortName The asyn network port connection to the Mythen
  * \param[in] maxBuffers The maximum number of NDArray buffers that the NDArrayPool for this driver is 
  *            allowed to allocate. Set this to -1 to allow an unlimited number of buffers.
  * \param[in] maxMemory The maximum amount of memory that the NDArrayPool for this driver is 
  *            allowed to allocate. Set this to -1 to allow an unlimited amount of memory.
  * \param[in] priority The thread priority for the asyn port driver thread if ASYN_CANBLOCK is set in asynFlags.
  * \param[in] stackSize The stack size for the asyn port driver thread if ASYN_CANBLOCK is set in asynFlags.
  */
mythen::mythen(const char *portName, const char *IPPortName,
                                int maxBuffers, size_t maxMemory,
                                int priority, int stackSize)

               : ADDriver(portName, 1, NUM_SD_PARAMS, maxBuffers, maxMemory,
               0, 0,             /* No interfaces beyond those set in ADDriver.cpp */
               ASYN_CANBLOCK | ASYN_MULTIDEVICE, 1, /* ASYN_CANBLOCK=1, ASYN_MULTIDEVICE=1, autoConnect=1 */
               priority, stackSize)
         // , pDetector(NULL)

{
    int status = asynSuccess;
    // NDArray *pData; 
    const char *functionName = "mythen";

    IPPortName_ = epicsStrDup(IPPortName);
    
    isBigEndian_ = EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG;

    /* Create the epicsEvents for signaling to the mythen task when acquisition starts and stops */
    this->startEventId_ = epicsEventCreate(epicsEventEmpty);
    if (!this->startEventId_) {
        printf("%s:%s epicsEventCreate failure for start event\n", 
            driverName, functionName);
        return;
    }

    // Connect to the server
    status = pasynOctetSyncIO->connect(IPPortName, 0, &pasynUserMeter_, NULL);
    if (status) {
        printf("%s:%s: error calling pasynOctetSyncIO->connect, status=%d, error=%s\n",
               driverName, functionName, status, pasynUserMeter_->errorMessage);
        return;
    }

    createParam(SDSettingString,          asynParamInt32,   &SDSetting); 
    createParam(SDDelayTimeString,        asynParamFloat64, &SDDelayTime); 
    createParam(SDThresholdString,        asynParamFloat64, &SDThreshold); 
    createParam(SDEnergyString,           asynParamFloat64, &SDEnergy); 
    createParam(SDUseFlatFieldString,     asynParamInt32,   &SDUseFlatField); 
    createParam(SDUseCountRateString,     asynParamInt32,   &SDUseCountRate); 
    createParam(SDUseBadChanIntrplString, asynParamInt32,   &SDUseBadChanIntrpl);
    createParam(SDBitDepthString,         asynParamInt32,   &SDBitDepth); 
    createParam(SDUseGatesString,         asynParamInt32,   &SDUseGates); 
    createParam(SDNumGatesString,         asynParamInt32,   &SDNumGates); 
    createParam(SDNumFramesString,        asynParamInt32,   &SDNumFrames); 
    createParam(SDTriggerString,          asynParamInt32,   &SDTrigger);
    createParam(SDResetString,            asynParamInt32,   &SDReset);
    createParam(SDTauString,              asynParamFloat64, &SDTau); 
    createParam(SDNModulesString,         asynParamInt32,   &SDNModules); 
    createParam(SDFirmwareVersionString,  asynParamOctet,   &SDFirmwareVersion);
    createParam(SDReadModeString,         asynParamInt32,   &SDReadMode);

    status =  setStringParam (ADManufacturer, "Dectris");
    status |= setStringParam (ADModel,        "Mythen");
    
    status |= getFirmware();
    status |= setStringParam (SDFirmwareVersion, firmwareVersion_);
    
    int sensorSizeX = MAX_DIMS;
    int  sensorSizeY = 1;
    status |= setIntegerParam(ADMaxSizeX, sensorSizeX);
    status |= setIntegerParam(ADMaxSizeY, sensorSizeY);

    int minX,  minY, sizeX, sizeY; 
    minX = 1; minY = 1; sizeX = MAX_DIMS; sizeY = 1; 
    status |= setIntegerParam(ADMinX,  minX);
    status |= setIntegerParam(ADMinY,  minY);
    status |= setIntegerParam(ADSizeX, sizeX);
    status |= setIntegerParam(ADSizeY, sizeY);

    status |= setIntegerParam(NDArraySize, 0);
    status |= setIntegerParam(NDDataType,  NDInt32);

    status |= setIntegerParam(ADImageMode, ADImageSingle);

    /* NOTE: these char type waveform record could not be initialized in iocInit 
     * Instead use autosave to restore their values.
     * It is left here only for references.
     * */
    status |= setIntegerParam(ADStatus, getStatus());
    
    //Get Firmware version
    
    
    // Read the current settings from the device.  This will set parameters in the parameter library.
    getSettings();

    int aux;
    //get nmodules and check for errors
    strcpy(outString_, "-get nmodules");
    status |= writeReadMeter();
    aux = stringToInt32(this->inString_);
    if (aux < 0) {
      asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
        "%s:%s: error, outString=%s, inString=%s\n",
        driverName, functionName, outString_, inString_);
      return;
    }
    this->nmodules=aux;
    status |= setIntegerParam(SDNModules, aux);
    detArray_ = (epicsInt32*) calloc(this->nmodules*1280, sizeof(epicsInt32));
    tmpArray_ = (epicsUInt32*) calloc(this->nmodules*1280, sizeof(epicsInt32));

    callParamCallbacks();

    if (status) {
        printf("%s: unable to read camera parameters\n", functionName);
        return;
    }

    /* Register the shutdown function for epicsAtExit */
    // epicsAtExit(c_shutdown, (void*)this); 

    /* Create the thread that runs acquisition */
    status = (epicsThreadCreate("acquisitionTask",
                                epicsThreadPriorityMedium,
                                epicsThreadGetStackSize(epicsThreadStackMedium),
                                (EPICSTHREADFUNC)acquisitionTaskC,
                                this) == NULL);

    /* Create the thread that polls status */
    //    status = (epicsThreadCreate("pollTask",
    //                                epicsThreadPriorityMedium,
    //                                epicsThreadGetStackSize(epicsThreadStackMedium),
    //                                (EPICSTHREADFUNC)pollTaskC,
    //                                this) == NULL);
}