asynNDArrayDriver::asynNDArrayDriver(const char *portName, int maxAddr, int maxBuffers,
                                     size_t maxMemory, int interfaceMask, int interruptMask,
                                     int asynFlags, int autoConnect, int priority, int stackSize)
    : asynPortDriver(portName, maxAddr, 
                     interfaceMask | asynInt32Mask | asynFloat64Mask | asynOctetMask | asynInt32ArrayMask | asynGenericPointerMask | asynDrvUserMask, 
                     interruptMask | asynInt32Mask | asynFloat64Mask | asynOctetMask | asynInt32ArrayMask | asynGenericPointerMask,
                     asynFlags, autoConnect, priority, stackSize),
      pNDArrayPool(NULL), queuedArrayCountMutex_(NULL), queuedArrayCount_(0),
      queuedArrayUpdateRun_(true)
{
    char versionString[20];
    static const char *functionName = "asynNDArrayDriver";

    /* Save the stack size and priority for other threads that this object may create */
    if (stackSize <= 0) stackSize = epicsThreadGetStackSize(epicsThreadStackMedium);
    threadStackSize_ = stackSize;
    if (priority <= 0) priority = epicsThreadPriorityMedium;
    threadPriority_ = priority;

    this->pNDArrayPoolPvt_ = new NDArrayPool(this, maxMemory);
    this->pNDArrayPool = this->pNDArrayPoolPvt_;
    this->queuedArrayCountMutex_ = new epicsMutex();

    /* Allocate pArray pointer array */
    this->pArrays = (NDArray **)calloc(maxAddr, sizeof(NDArray *));
    this->pAttributeList = new NDAttributeList();
    
    createParam(NDPortNameSelfString,         asynParamOctet,           &NDPortNameSelf);
    createParam(NDADCoreVersionString,        asynParamOctet,           &NDADCoreVersion);
    createParam(NDDriverVersionString,        asynParamOctet,           &NDDriverVersion);
    createParam(NDArraySizeXString,           asynParamInt32,           &NDArraySizeX);
    createParam(NDArraySizeYString,           asynParamInt32,           &NDArraySizeY);
    createParam(NDArraySizeZString,           asynParamInt32,           &NDArraySizeZ);
    createParam(NDArraySizeString,            asynParamInt32,           &NDArraySize);
    createParam(NDNDimensionsString,          asynParamInt32,           &NDNDimensions);
    createParam(NDDimensionsString,           asynParamInt32,           &NDDimensions);
    createParam(NDDataTypeString,             asynParamInt32,           &NDDataType);
    createParam(NDColorModeString,            asynParamInt32,           &NDColorMode);
    createParam(NDUniqueIdString,             asynParamInt32,           &NDUniqueId);
    createParam(NDTimeStampString,            asynParamFloat64,         &NDTimeStamp);
    createParam(NDEpicsTSSecString,           asynParamInt32,           &NDEpicsTSSec);
    createParam(NDEpicsTSNsecString,          asynParamInt32,           &NDEpicsTSNsec);
    createParam(NDBayerPatternString,         asynParamInt32,           &NDBayerPattern);
    createParam(NDCodecString,                asynParamOctet,           &NDCodec);
    createParam(NDCompressedSizeString,       asynParamInt32,           &NDCompressedSize);
    createParam(NDArrayCounterString,         asynParamInt32,           &NDArrayCounter);
    createParam(NDFilePathString,             asynParamOctet,           &NDFilePath);
    createParam(NDFilePathExistsString,       asynParamInt32,           &NDFilePathExists);
    createParam(NDFileNameString,             asynParamOctet,           &NDFileName);
    createParam(NDFileNumberString,           asynParamInt32,           &NDFileNumber);
    createParam(NDFileTemplateString,         asynParamOctet,           &NDFileTemplate);
    createParam(NDAutoIncrementString,        asynParamInt32,           &NDAutoIncrement);
    createParam(NDFullFileNameString,         asynParamOctet,           &NDFullFileName);
    createParam(NDFileFormatString,           asynParamInt32,           &NDFileFormat);
    createParam(NDAutoSaveString,             asynParamInt32,           &NDAutoSave);
    createParam(NDWriteFileString,            asynParamInt32,           &NDWriteFile);
    createParam(NDReadFileString,             asynParamInt32,           &NDReadFile);
    createParam(NDFileWriteModeString,        asynParamInt32,           &NDFileWriteMode);
    createParam(NDFileWriteStatusString,      asynParamInt32,           &NDFileWriteStatus);
    createParam(NDFileWriteMessageString,     asynParamOctet,           &NDFileWriteMessage);
    createParam(NDFileNumCaptureString,       asynParamInt32,           &NDFileNumCapture);
    createParam(NDFileNumCapturedString,      asynParamInt32,           &NDFileNumCaptured);
    createParam(NDFileCaptureString,          asynParamInt32,           &NDFileCapture);   
    createParam(NDFileDeleteDriverFileString, asynParamInt32,           &NDFileDeleteDriverFile);
    createParam(NDFileLazyOpenString,         asynParamInt32,           &NDFileLazyOpen);
    createParam(NDFileCreateDirString,        asynParamInt32,           &NDFileCreateDir);
    createParam(NDFileTempSuffixString,       asynParamOctet,           &NDFileTempSuffix);
    createParam(NDAttributesFileString,       asynParamOctet,           &NDAttributesFile);
    createParam(NDAttributesStatusString,     asynParamInt32,           &NDAttributesStatus);
    createParam(NDAttributesMacrosString,     asynParamOctet,           &NDAttributesMacros);
    createParam(NDArrayDataString,            asynParamGenericPointer,  &NDArrayData);
    createParam(NDArrayCallbacksString,       asynParamInt32,           &NDArrayCallbacks);
    createParam(NDPoolMaxBuffersString,       asynParamInt32,           &NDPoolMaxBuffers);
    createParam(NDPoolAllocBuffersString,     asynParamInt32,           &NDPoolAllocBuffers);
    createParam(NDPoolFreeBuffersString,      asynParamInt32,           &NDPoolFreeBuffers);
    createParam(NDPoolMaxMemoryString,        asynParamFloat64,         &NDPoolMaxMemory);
    createParam(NDPoolUsedMemoryString,       asynParamFloat64,         &NDPoolUsedMemory);
    createParam(NDPoolEmptyFreeListString,    asynParamInt32,           &NDPoolEmptyFreeList);
    createParam(NDNumQueuedArraysString,      asynParamInt32,           &NDNumQueuedArrays);

    /* Here we set the values of read-only parameters and of read/write parameters that cannot
     * or should not get their values from the database.  Note that values set here will override
     * those in the database for output records because if asyn device support reads a value from 
     * the driver with no error during initialization then it sets the output record to that value.  
     * If a value is not set here then the read request will return an error (uninitialized).
     * Values set here will be overridden by values from save/restore if they exist. */
    setStringParam (NDPortNameSelf, portName);
    epicsSnprintf(versionString, sizeof(versionString), "%d.%d.%d", 
                  ADCORE_VERSION, ADCORE_REVISION, ADCORE_MODIFICATION);
    setStringParam(NDADCoreVersion, versionString);
    // We set the driver version to the same thing, which is appropriate for plugins in ADCore
    // Other drivers need to set this after this constructor
    setStringParam(NDDriverVersion, versionString);
    setIntegerParam(NDArraySizeX,   0);
    setIntegerParam(NDArraySizeY,   0);
    setIntegerParam(NDArraySizeZ,   0);
    setIntegerParam(NDArraySize,    0);
    setIntegerParam(NDNDimensions,  0);
    setIntegerParam(NDColorMode,    NDColorModeMono);
    setIntegerParam(NDUniqueId,     0);
    setDoubleParam (NDTimeStamp,    0.);
    setIntegerParam(NDEpicsTSSec,   0);
    setIntegerParam(NDEpicsTSNsec,  0);
    setIntegerParam(NDBayerPattern, 0);
    setIntegerParam(NDArrayCounter, 0);
    /* Set the initial values of FileSave, FileRead, and FileCapture so the readbacks are initialized */
    setIntegerParam(NDWriteFile, 0);
    setIntegerParam(NDReadFile, 0);
    setIntegerParam(NDFileCapture, 0);
    setIntegerParam(NDFileWriteStatus, 0);
    setStringParam (NDFileWriteMessage, "");
    /* We set FileTemplate to a reasonable value because it cannot be defined in the database, since it is a
     * waveform record. However, the waveform record does not currently read the driver value for initialization! */
    setStringParam (NDFilePath, "");
    setStringParam (NDFileName, "");
    setIntegerParam(NDFileNumber, 0);
    setIntegerParam(NDAutoIncrement, 0);
    setStringParam (NDFileTemplate, "%s%s_%3.3d.dat");
    setIntegerParam(NDFileNumCaptured, 0);
    setIntegerParam(NDFileCreateDir, 0);
    setStringParam (NDFileTempSuffix, "");
    setStringParam (NDAttributesFile, "");
    setIntegerParam(NDAttributesStatus, NDAttributesFileNotFound);
    setStringParam (NDAttributesMacros, "");

    setIntegerParam(NDPoolAllocBuffers, this->pNDArrayPool->getNumBuffers());
    setIntegerParam(NDPoolFreeBuffers, this->pNDArrayPool->getNumFree());
    setDoubleParam(NDPoolMaxMemory, 0);
    setDoubleParam(NDPoolUsedMemory, 0);

    setIntegerParam(NDNumQueuedArrays, 0);

    queuedArrayEvent_ = epicsEventCreate(epicsEventEmpty);
    queuedArrayUpdateDone_ = epicsEventCreate(epicsEventEmpty);
    /* Create the thread that updates the queued array count */
    
    char taskName[100];
    epicsSnprintf(taskName, sizeof(taskName)-1, "%s_updateQueuedArrayCount", portName);
    epicsThreadId queuedArrayThreadId = epicsThreadCreate(taskName,
                                                          this->threadPriority_,
                                                          this->threadStackSize_,
                                                          (EPICSTHREADFUNC)updateQueuedArrayCountC, this);
    if (queuedArrayThreadId == 0) {
        asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
            "%s::%s error creating updateQueuedArrayCount thread\n", 
            driverName, functionName);
    }

}
Beispiel #2
0
int main (int argc, char *argv[])
{
    int i;
    int result;                 /* CA result */
    OutputT format = plain;     /* User specified format */
    RequestT request = get;     /* User specified request type */
    int isArray = 0;            /* Flag for array operation */
    int enumAsString = 0;       /* Force ENUM values to be strings */

    int count = 1;
    int opt;                    /* getopt() current option */
    chtype dbrType = DBR_STRING;
    char *pend;
    EpicsStr *sbuf;
    double *dbuf;
    char *cbuf = 0;
    char *ebuf = 0;
    void *pbuf;
    int len = 0;
    int waitStatus;
    struct dbr_gr_enum bufGrEnum;

    int nPvs;                   /* Number of PVs */
    pv* pvs;                /* Array of PV structures */

    LINE_BUFFER(stdout);        /* Configure stdout buffering */
    putenv("POSIXLY_CORRECT="); /* Behave correct on GNU getopt systems */

    while ((opt = getopt(argc, argv, ":cnlhatsS#:w:p:F:")) != -1) {
        switch (opt) {
        case 'h':               /* Print usage */
            usage();
            return 0;
        case 'n':               /* Force interpret ENUM as index number */
            enumAsNr = 1;
            enumAsString = 0;
            break;
        case 's':               /* Force interpret ENUM as menu string */
            enumAsString = 1;
            enumAsNr = 0;
            break;
        case 'S':               /* Treat char array as (long) string */
            charArrAsStr = 1;
            isArray = 0;
            break;
        case 't':               /* Select terse output format */
            format = terse;
            break;
        case 'l':               /* Select long output format */
            format = all;
            break;
        case 'a':               /* Select array mode */
            isArray = 1;
            charArrAsStr = 0;
            break;
        case 'c':               /* Select put_callback mode */
            request = callback;
            break;
        case 'w':               /* Set CA timeout value */
            if(epicsScanDouble(optarg, &caTimeout) != 1)
            {
                fprintf(stderr, "'%s' is not a valid timeout value "
                        "- ignored. ('caput -h' for help.)\n", optarg);
                caTimeout = DEFAULT_TIMEOUT;
            }
            break;
        case '#':               /* Array count */
            if (sscanf(optarg,"%d", &count) != 1)
            {
                fprintf(stderr, "'%s' is not a valid array element count "
                        "- ignored. ('caput -h' for help.)\n", optarg);
                count = 0;
            }
            break;
        case 'p':               /* CA priority */
            if (sscanf(optarg,"%u", &caPriority) != 1)
            {
                fprintf(stderr, "'%s' is not a valid CA priority "
                        "- ignored. ('caget -h' for help.)\n", optarg);
                caPriority = DEFAULT_CA_PRIORITY;
            }
            if (caPriority > CA_PRIORITY_MAX) caPriority = CA_PRIORITY_MAX;
            break;
        case 'F':               /* Store this for output and tool_lib formatting */
            fieldSeparator = (char) *optarg;
            break;
        case '?':
            fprintf(stderr,
                    "Unrecognized option: '-%c'. ('caput -h' for help.)\n",
                    optopt);
            return 1;
        case ':':
            fprintf(stderr,
                    "Option '-%c' requires an argument. ('caput -h' for help.)\n",
                    optopt);
            return 1;
        default :
            usage();
            return 1;
        }
    }

    nPvs = argc - optind;       /* Remaining arg list are PV names and values */

    if (nPvs < 1) {
        fprintf(stderr, "No pv name specified. ('caput -h' for help.)\n");
        return 1;
    }
    if (nPvs == 1) {
        fprintf(stderr, "No value specified. ('caput -h' for help.)\n");
        return 1;
    }

    nPvs = 1;                   /* One PV - the rest is value(s) */

    epId = epicsEventCreate(epicsEventEmpty);  /* Create empty EPICS event (semaphore) */

                                /* Start up Channel Access */

    result = ca_context_create(ca_enable_preemptive_callback);
    if (result != ECA_NORMAL) {
        fprintf(stderr, "CA error %s occurred while trying "
                "to start channel access.\n", ca_message(result));
        return 1;
    }
                                /* Allocate PV structure array */

    pvs = calloc (nPvs, sizeof(pv));
    if (!pvs) {
        fprintf(stderr, "Memory allocation for channel structure failed.\n");
        return 1;
    }
                                /* Connect channels */

    pvs[0].name = argv[optind] ;   /* Copy PV name from command line */

    result = connect_pvs(pvs, nPvs); /* If the connection fails, we're done */
    if (result) {
        ca_context_destroy();
        return result;
    }

                                /* Get values from command line */
    optind++;

    if (isArray) {
        optind++;               /* In case of array skip first value (nr
                                 * of elements) - actual number of values is used */
        count = argc - optind;

    } else {                    /* Concatenate the remaining line to one string
                                 * (sucks but is compatible to the former version) */
        for (i = optind; i < argc; i++) {
            len += strlen(argv[i]);
            len++;
        }
        cbuf = calloc(len, sizeof(char));
        if (!cbuf) {
            fprintf(stderr, "Memory allocation failed.\n");
            return 1;
        }
        strcpy(cbuf, argv[optind]);

        if (argc > optind+1) {
            for (i = optind + 1; i < argc; i++) {
                strcat(cbuf, " ");
                strcat(cbuf, argv[i]); 
            }
        }

        if ((argc - optind) >= 1)
            count = 1;
        argv[optind] = cbuf;
    }

    sbuf = calloc (count, sizeof(EpicsStr));
    dbuf = calloc (count, sizeof(double));
    if(!sbuf || !dbuf) {
        fprintf(stderr, "Memory allocation failed\n");
        return 1;
    }

                                /*  ENUM? Special treatment */

    if (ca_field_type(pvs[0].chid) == DBR_ENUM) {

                                /* Get the ENUM strings */

        result = ca_array_get (DBR_GR_ENUM, 1, pvs[0].chid, &bufGrEnum);
        result = ca_pend_io(caTimeout);
        if (result == ECA_TIMEOUT) {
            fprintf(stderr, "Read operation timed out: ENUM data was not read.\n");
            return 1;
        }

        if (enumAsNr) {         /* Interpret values as numbers */

            for (i = 0; i < count; ++i) {
                dbuf[i] = epicsStrtod(*(argv+optind+i), &pend);
                if (*(argv+optind+i) == pend) { /* Conversion didn't work */
                    fprintf(stderr, "Enum index value '%s' is not a number.\n",
                            *(argv+optind+i));
                    return 1;
                }
                if (dbuf[i] >= bufGrEnum.no_str) {
                    fprintf(stderr, "Warning: enum index value '%s' may be too large.\n",
                            *(argv+optind+i));
                }
            }
            dbrType = DBR_DOUBLE;

        } else {                /* Interpret values as strings */

            for (i = 0; i < count; ++i) {
                epicsStrnRawFromEscaped(sbuf[i], sizeof(EpicsStr), *(argv+optind+i), sizeof(EpicsStr));
                *( sbuf[i]+sizeof(EpicsStr)-1 ) = '\0';
                dbrType = DBR_STRING;

                                /* Compare to ENUM strings */
                for (len = 0; len < bufGrEnum.no_str; len++)
                    if (!strcmp(sbuf[i], bufGrEnum.strs[len]))
                        break;

                if (len >= bufGrEnum.no_str) {
                                         /* Not a string? Try as number */
                    dbuf[i] = epicsStrtod(sbuf[i], &pend);
                    if (sbuf[i] == pend || enumAsString) {
                        fprintf(stderr, "Enum string value '%s' invalid.\n", sbuf[i]);
                        return 1;
                    }
                    if (dbuf[i] >= bufGrEnum.no_str) {
                        fprintf(stderr, "Warning: enum index value '%s' may be too large.\n", sbuf[i]);
                    }
                    dbrType = DBR_DOUBLE;
                }
            }
        }

    } else {                    /* Not an ENUM */

        if (charArrAsStr) {
            dbrType = DBR_CHAR;
            ebuf = calloc(len, sizeof(char));
            if(!ebuf) {
                fprintf(stderr, "Memory allocation failed\n");
                return 1;
            }
            count = epicsStrnRawFromEscaped(ebuf, len, cbuf, len-1) + 1;
        } else {
            for (i = 0; i < count; ++i) {
                epicsStrnRawFromEscaped(sbuf[i], sizeof(EpicsStr), *(argv+optind+i), sizeof(EpicsStr));
                *( sbuf[i]+sizeof(EpicsStr)-1 ) = '\0';
            }
            dbrType = DBR_STRING;
        }
    }

                                /* Read and print old data */
    if (format != terse) {
        printf("Old : ");
        result = caget(pvs, nPvs, format, 0, 0);
    }

                                /* Write new data */
    if (dbrType == DBR_STRING) pbuf = sbuf;
    else if (dbrType == DBR_CHAR) pbuf = ebuf;
    else pbuf = dbuf;

    if (request == callback) {
        /* Use callback version of put */
        pvs[0].status = ECA_NORMAL;   /* All ok at the moment */
        result = ca_array_put_callback (
            dbrType, count, pvs[0].chid, pbuf, put_event_handler, (void *) pvs);
    } else {
        /* Use standard put with defined timeout */
        result = ca_array_put (dbrType, count, pvs[0].chid, pbuf);
    }
    result = ca_pend_io(caTimeout);
    if (result == ECA_TIMEOUT) {
        fprintf(stderr, "Write operation timed out: Data was not written.\n");
        return 1;
    }
    if (request == callback) {   /* Also wait for callbacks */
        waitStatus = epicsEventWaitWithTimeout( epId, caTimeout );
        if (waitStatus)
            fprintf(stderr, "Write callback operation timed out\n");

        /* retrieve status from callback */
        result = pvs[0].status;
    }

    if (result != ECA_NORMAL) {
        fprintf(stderr, "Error occured writing data.\n");
        return 1;
    }

                                /* Read and print new data */
    if (format != terse)
        printf("New : ");

    result = caget(pvs, nPvs, format, 0, 0);

                                /* Shut down Channel Access */
    ca_context_destroy();

    return result;
}
Beispiel #3
0
/*Constructor */
drvSIS3820::drvSIS3820(const char *portName, int baseAddress, int interruptVector, int interruptLevel, 
                       int maxChans, int maxSignals, bool useDma, int fifoBufferWords)
  :  drvSIS38XX(portName, maxChans, maxSignals),
     useDma_(useDma)
{
  int status;
  epicsUInt32 controlStatusReg;
  epicsUInt32 moduleID;
  static const char* functionName="SIS3820";
  
  setIntegerParam(SIS38XXModel_, MODEL_SIS3820);
  
  /* Call devLib to get the system address that corresponds to the VME
   * base address of the board.
   */
  status = devRegisterAddress("drvSIS3820",
                               SIS3820_ADDRESS_TYPE,
                               (size_t)baseAddress,
                               SIS3820_BOARD_SIZE,
                               (volatile void **)&registers_);

  if (status) {
    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
              "%s:%s: %s, Can't register VME address 0x%x\n", 
              driverName, functionName, portName, baseAddress);
    return;
  }
  asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, 
            "%s:%s: Registered VME address: 0x%x to local address: %p size: 0x%X\n", 
            driverName, functionName, baseAddress, registers_, SIS3820_BOARD_SIZE);

  /* Call devLib to get the system address that corresponds to the VME
   * FIFO address of the board.
   */
  fifoBaseVME_ = (epicsUInt32 *)(baseAddress + SIS3820_FIFO_BASE);
  status = devRegisterAddress("drvSIS3820",
                              SIS3820_ADDRESS_TYPE,
                              (size_t)fifoBaseVME_,
                              SIS3820_FIFO_BYTE_SIZE,
                              (volatile void **)&fifoBaseCPU_);

  if (status) {
    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
              "%s:%s: %s, Can't register FIFO address 0x%x\n", 
              driverName, functionName, portName, baseAddress + SIS3820_FIFO_BASE);
    return;
  }

  asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, 
            "%s:%s: Registered VME FIFO address: %p to local address: %p size: 0x%X\n", 
            driverName, functionName, fifoBaseVME_, 
            fifoBaseCPU_, SIS3820_FIFO_BYTE_SIZE);

  /* Probe VME bus to see if card is there */
  status = devReadProbe(4, (char *) &(registers_->control_status_reg),
                       (char *) &controlStatusReg);
  if (status) {
    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
              "%s:%s: devReadProbe failure for address %p = %d\n", 
              driverName, functionName, &registers_->control_status_reg, status);
    return;
  }

  /* Get the module info from the card */
  moduleID = (registers_->moduleID_reg & 0xFFFF0000) >> 16;
  asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, 
            "%s:%s: module ID=%x\n", 
            driverName, functionName, moduleID);
  firmwareVersion_ = registers_->moduleID_reg & 0x0000FFFF;
  setIntegerParam(SIS38XXFirmware_, firmwareVersion_);
  asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, 
            "%s:%s: firmware=%d\n",
            driverName, functionName, firmwareVersion_);

  // Allocate FIFO readout buffer
  // fifoBufferWords input argument is in words, must be less than SIS3820_FIFO_WORD_SIZE
  if (fifoBufferWords == 0) fifoBufferWords = SIS3820_FIFO_WORD_SIZE;
  if (fifoBufferWords > SIS3820_FIFO_WORD_SIZE) fifoBufferWords = SIS3820_FIFO_WORD_SIZE;
  fifoBufferWords_ = fifoBufferWords;
#ifdef vxWorks
  fifoBuffer_ = (epicsUInt32*) memalign(8, fifoBufferWords_*sizeof(epicsUInt32));
#else
  void *ptr;
  status = posix_memalign(&ptr, 8, fifoBufferWords_*sizeof(epicsUInt32));
  if(status != 0) {
    printf("Error: posix_memalign status = %d\n", status);
  }
  fifoBuffer_ = (epicsUInt32*)ptr;
#endif
  if (fifoBuffer_ == NULL) {
    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
              "%s:%s: posix_memalign failure for fifoBuffer_ = %d\n", 
              driverName, functionName, status);
    return;
  }
  
  dmaDoneEventId_ = epicsEventCreate(epicsEventEmpty);
  // Create the DMA ID
  if (useDma_) {
    dmaId_ = sysDmaCreate(dmaCallbackC, (void*)this);
    if (dmaId_ == 0 || (int)dmaId_ == -1) {
      asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
                "%s:%s: sysDmaCreate failed, errno=%d. Disabling use of DMA.\n",
                driverName, functionName, errno);
      useDma_ = false;
    }
  }
 
  /* Reset card */
  asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, 
            "%s:%s: resetting port %s\n", 
            driverName, functionName, portName);
  registers_->key_reset_reg = 1;

  /* Clear FIFO */
  asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, 
           "%s:%s: clearing FIFO\n",
           driverName, functionName);
  resetFIFO();
  
  // Disable 25MHz test pulses and test mode
  registers_->control_status_reg = CTRL_COUNTER_TEST_25MHZ_DISABLE;
  registers_->control_status_reg = CTRL_COUNTER_TEST_MODE_DISABLE;

  /* Set up the interrupt service routine */
  asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, 
            "%s:%s: interruptServiceRoutine pointer %p\n",
            driverName, functionName, intFuncC);

  status = devConnectInterruptVME(interruptVector, intFuncC, this);
  if (status) {
    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
              "%s:%s: Can't connect to vector % d\n", 
              driverName, functionName, interruptVector);
    return;
  }
  asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, 
            "%s:%s: Connected interrupt vector: %d\n\n",
            driverName, functionName, interruptVector);
  
  /* Write interrupt level to hardware */
  registers_->irq_config_reg &= ~SIS3820_IRQ_LEVEL_MASK;
  registers_->irq_config_reg |= (interruptLevel << 8);
  asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, 
            "%s:%s: irq after setting IntLevel= 0x%x\n", 
             driverName, functionName, registers_->irq_config_reg);

  /* Write interrupt vector to hardware */
  registers_->irq_config_reg &= ~SIS3820_IRQ_VECTOR_MASK;
  registers_->irq_config_reg |= interruptVector;
  asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, 
            "%s:%s: irq = 0x%08x\n", 
            driverName, functionName, registers_->irq_config_reg);
            
  /* Initialize board in MCS mode. This will also set the initial value of the operation mode register. */
  setAcquireMode(ACQUIRE_MODE_MCS);

  /* Create the thread that reads the FIFO */
  if (epicsThreadCreate("SIS3820FIFOThread",
                         epicsThreadPriorityLow,
                         epicsThreadGetStackSize(epicsThreadStackMedium),
                         (EPICSTHREADFUNC)readFIFOThreadC,
                         this) == NULL) {
    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
              "%s:%s: epicsThreadCreate failure\n", 
              driverName, functionName);
    return;
  }
  else
    asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, 
            "%s:%s: epicsThreadCreate success\n", 
            driverName, functionName);

  erase();

  /* Enable interrupts in hardware */  
  asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, 
            "%s:%s: irq before enabling interrupts= 0x%08x\n", 
            driverName, functionName, registers_->irq_config_reg);

  registers_->irq_config_reg |= SIS3820_IRQ_ENABLE;

  /* Enable interrupt level in EPICS */
  status = devEnableInterruptLevel(intVME, interruptLevel);
  if (status) {
    asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
              "%s:%s: Can't enable enterrupt level %d\n", 
              driverName, functionName, interruptLevel);
    return;
  }
  
  exists_ = true;
  return;
}
Beispiel #4
0
int main(int argc,char **argv)
{
    char   *pval;
    double sleepSecs = 0.0;
    int	    clearEvery = 0;
    int     indValue = 1;
    int     indNumberCallback = 1;

    while((argc>1) && (argv[1][0] == '-')) {
        int i;
        char option;
        int  narg;
        option = toupper((argv[1])[1]);
        pval = argv[2];
        argc -= 1; narg = 1;
        if(option=='S') {
            sscanf(pval,"%lf",&sleepSecs);
            argc -= 1; ++narg;
        } else if(option=='C') {
            sscanf(pval,"%d",&clearEvery);
            argc -= 1; ++narg;
        } else if(option=='V') {
            verbose = 1;
        } else {
            usageExit();
        }
        for(i=1; i<argc; i++) argv[i] = argv[i + narg];
    }

    if(argc != 4) usageExit();
    pvname = argv[1];
    pvalue1 = argv[2];
    pvalue2 = argv[3];
    pevent = epicsEventCreate(epicsEventEmpty);
    SEVCHK(ca_context_create(ca_enable_preemptive_callback),
        "ca_task_initialize");
    while(1) {
        SEVCHK(ca_search(pvname,&mychid),"ca_search_and_connect");
        if(ca_pend_io(3.0)!=ECA_NORMAL) {
            epicsThreadSleep(5.0);
            continue;
        }
        while(1) {
            epicsEventWaitStatus status;
            if(indValue==0) {
                indValue = 1; pvalue = pvalue2;
            } else {
                indValue = 0; pvalue=pvalue1;
            }
            if(++indNumberCallback >= MAXnumberCallback) indNumberCallback=0;
            numberCallback[indNumberCallback] = ++expectedCallback;
            status = ca_array_put_callback(DBR_STRING,1,mychid,
                pvalue,putCallback,&numberCallback[indNumberCallback]);
            if(status!=ECA_NORMAL) {
                printf("ca_array_put_callback %s\n",ca_message(status));
                epicsThreadSleep(2.0);
                continue;
            }
            if((clearEvery>0) 
            && ((expectedCallback % clearEvery)==0)) {
                ca_flush_io();
                epicsThreadSleep(sleepSecs);
                SEVCHK(ca_clear_channel(mychid),"ca_clear_channel");
                ca_flush_io();
                expectedCallback = 0;
                epicsThreadSleep(sleepSecs);
                if(verbose) {
                    printTime();
                    printf("Issued ca_clear_channel expectedCallback %d\n",
                        expectedCallback);
                }
                break;
            }
            ca_flush_io();
            if(verbose) {
                printTime();
                printf("Issued ca_put_callback expectedCallback %d\n",
                    expectedCallback);
            }
            while(1) {
                status = epicsEventWaitWithTimeout(pevent,10.0);
                if(status==epicsEventWaitTimeout) {
                    if(verbose) {
                        printTime();
                        printf("timeout after 10 seconds\n");
                    }
                    continue;
                }
                break;
            }
            if(status!=epicsEventWaitOK) {
                int i;
                printTime();
                printf("eventWait status %d\n",status);
                for(i=0; i<MAXnumberCallback; i++) numberCallback[i]=0;
            }
            epicsThreadSleep(sleepSecs);
        }
    }
    ca_task_exit();
    return(0);
}
/** Constructor for the testAsynPortDriver class.
  * Calls constructor for the asynPortDriver base class.
  * \param[in] portName The name of the asyn port driver to be created.
  * \param[in] maxPoints The maximum  number of points in the volt and time arrays */
testAsynPortDriver::testAsynPortDriver(const char *portName, int maxPoints) 
   : asynPortDriver(portName, 
                    1, /* maxAddr */ 
                    (int)NUM_SCOPE_PARAMS,
                    asynInt32Mask | asynFloat64Mask | asynFloat64ArrayMask | asynEnumMask | asynDrvUserMask, /* Interface mask */
                    asynInt32Mask | asynFloat64Mask | asynFloat64ArrayMask | asynEnumMask,  /* Interrupt mask */
                    0, /* asynFlags.  This driver does not block and it is not multi-device, so flag is 0 */
                    1, /* Autoconnect */
                    0, /* Default priority */
                    0) /* Default stack size*/    
{
    asynStatus status;
    int i;
    const char *functionName = "testAsynPortDriver";

    /* Make sure maxPoints is positive */
    if (maxPoints < 1) maxPoints = 100;
    
    /* Allocate the waveform array */
    pData_ = (epicsFloat64 *)calloc(maxPoints, sizeof(epicsFloat64));

    /* Allocate the time base array */
    pTimeBase_ = (epicsFloat64 *)calloc(maxPoints, sizeof(epicsFloat64));
    /* Set the time base array */
    for (i=0; i<maxPoints; i++) pTimeBase_[i] = (double)i / (maxPoints-1) * NUM_DIVISIONS;
    
    eventId_ = epicsEventCreate(epicsEventEmpty);
    createParam(P_RunString,                asynParamInt32,         &P_Run);
    createParam(P_MaxPointsString,          asynParamInt32,         &P_MaxPoints);
    createParam(P_TimePerDivString,         asynParamFloat64,       &P_TimePerDiv);
    createParam(P_TimePerDivSelectString,   asynParamInt32,         &P_TimePerDivSelect);
    createParam(P_VertGainString,           asynParamFloat64,       &P_VertGain);
    createParam(P_VertGainSelectString,     asynParamInt32,         &P_VertGainSelect);
    createParam(P_VoltsPerDivString,        asynParamFloat64,       &P_VoltsPerDiv);
    createParam(P_VoltsPerDivSelectString,  asynParamInt32,         &P_VoltsPerDivSelect);
    createParam(P_VoltOffsetString,         asynParamFloat64,       &P_VoltOffset);
    createParam(P_TriggerDelayString,       asynParamFloat64,       &P_TriggerDelay);
    createParam(P_NoiseAmplitudeString,     asynParamFloat64,       &P_NoiseAmplitude);
    createParam(P_UpdateTimeString,         asynParamFloat64,       &P_UpdateTime);
    createParam(P_WaveformString,           asynParamFloat64Array,  &P_Waveform);
    createParam(P_TimeBaseString,           asynParamFloat64Array,  &P_TimeBase);
    createParam(P_MinValueString,           asynParamFloat64,       &P_MinValue);
    createParam(P_MaxValueString,           asynParamFloat64,       &P_MaxValue);
    createParam(P_MeanValueString,          asynParamFloat64,       &P_MeanValue);
    
    for (i=0; i<NUM_VERT_SELECTIONS; i++) {
        // Compute vertical volts per division in mV
        voltsPerDivValues_[i] = 0;
        voltsPerDivStrings_[i] = (char *)calloc(MAX_ENUM_STRING_SIZE, sizeof(char));
        voltsPerDivSeverities_[i] = 0;
    } 

    /* Set the initial values of some parameters */
    setIntegerParam(P_MaxPoints,         maxPoints);
    setIntegerParam(P_Run,               0);
    setIntegerParam(P_VertGainSelect,    10);
    setVertGain();
    setDoubleParam (P_VoltsPerDiv,       1.0);
    setDoubleParam (P_VoltOffset,        0.0);
    setDoubleParam (P_TriggerDelay,      0.0);
    setDoubleParam (P_TimePerDiv,        0.001);
    setDoubleParam (P_UpdateTime,        0.5);
    setDoubleParam (P_NoiseAmplitude,    0.1);
    setDoubleParam (P_MinValue,          0.0);
    setDoubleParam (P_MaxValue,          0.0);
    setDoubleParam (P_MeanValue,         0.0);
    
    
    /* Create the thread that computes the waveforms in the background */
    status = (asynStatus)(epicsThreadCreate("testAsynPortDriverTask",
                          epicsThreadPriorityMedium,
                          epicsThreadGetStackSize(epicsThreadStackMedium),
                          (EPICSTHREADFUNC)::simTask,
                          this) == NULL);
    if (status) {
        printf("%s:%s: epicsThreadCreate failure\n", driverName, functionName);
        return;
    }
}