Ejemplo n.º 1
0
void drvSIS3801::resetScaler()
{
  //static const char *functionName="resetScaler";
  setAcquireMode(ACQUIRE_MODE_SCALER);
  resetFIFO();
  nextChan_ = 0;
  nextSignal_ = 0;
}
Ejemplo n.º 2
0
void drvSIS3820::resetScaler()
{
  /* Reset scaler */
  setAcquireMode(ACQUIRE_MODE_SCALER);
  registers_->key_op_disable_reg = 1;
  resetFIFO();
  registers_->key_counter_clear = 1;
}
Ejemplo n.º 3
0
void drvSIS3801::startScaler()
{
  //static const char *functionName="startScaler";

  setAcquireMode(ACQUIRE_MODE_SCALER);
  
  registers_->csr_reg = CONTROL_M_ENABLE_10MHZ_LNE_PRESCALER;
  registers_->csr_reg = CONTROL_M_DISABLE_LNE_PRESCALER;
  registers_->prescale_factor_reg = ((SIS3801_10MHZ_CLOCK / SIS3801_SCALER_MODE_RATE) - 1);
  registers_->csr_reg = CONTROL_M_ENABLE_LNE_PRESCALER;
  registers_->enable_next_reg = 1;
  /* Enable counting bit in CSR */
  registers_->csr_reg = CONTROL_M_CLEAR_SOFTWARE_DISABLE;
  registers_->soft_next_reg = 1; 
  // Wake up the FIFO reading thread
  eventType_ = EventStartScaler;
  epicsEventSignal(readFIFOEventId_);
}
Ejemplo n.º 4
0
void drvSIS3820::startMCSAcquire()
{
  int countOnStart;
  int channelAdvanceSource;
  //static const char *functionName="startMCSAcquire";
  
  getIntegerParam(SIS38XXCountOnStart_, &countOnStart);
  getIntegerParam(mcaChannelAdvanceSource_, &channelAdvanceSource);

  setAcquireMode(ACQUIRE_MODE_MCS);

  if (channelAdvanceSource == mcaChannelAdvance_Internal) 
    registers_->key_op_enable_reg = 1;
  else if (channelAdvanceSource == mcaChannelAdvance_External) {
    if (countOnStart)
      registers_->key_op_enable_reg = 1;
    else
      registers_->key_op_arm_reg = 1;
  }
}
Ejemplo n.º 5
0
/*Constructor */
drvSIS3801::drvSIS3801(const char *portName, int baseAddress, int interruptVector, int interruptLevel, 
                       int maxChans, int maxSignals)
  :  drvSIS38XX(portName, maxChans, maxSignals)

{
  int status;
  epicsUInt32 controlStatusReg;
  epicsUInt32 moduleID;
  static const char* functionName="SIS3801";

  setIntegerParam(SIS38XXModel_, MODEL_SIS3801);
  
  /* Call devLib to get the system address that corresponds to the VME
   * base address of the board.
   */
  status = devRegisterAddress("drvSIS3801",
                               SIS3801_ADDRESS_TYPE,
                               (size_t)baseAddress,
                               SIS3801_BOARD_SIZE,
                               (volatile void **)&registers_);

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

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

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

  // Create the mutex used to lock access to the FIFO
  fifoLockId_ = epicsMutexCreate();

  /* 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();

  setControlStatusReg();

  /* Initialize board in MCS mode */
  setAcquireMode(ACQUIRE_MODE_MCS);

  /* Set number of readout channels to maxSignals
   * Assumes that the lower channels will be used first, and the only unused
   * channels will be at the upper end of the channel range.
   * Create a mask with zeros in the rightmost maxSignals bits,
   * 1 in all higher order bits. */
  registers_->copy_disable_reg = 0xffffffff<<maxSignals_;
  asynPrint(pasynUserSelf, ASYN_TRACE_FLOW,
            "%s:%s: setting copy disable register=0x%08x\n",
            driverName, functionName, 0xffffffff<<maxSignals_);

  /* 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 */
  asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, 
            "%s:%s: irq before setting IntLevel= 0x%x\n", 
            driverName, functionName, registers_->irq_reg);

  registers_->irq_reg |= (interruptLevel << 8);

  asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, 
            "%s:%s: irq after setting IntLevel= 0x%x\n", 
             driverName, functionName, registers_->irq_reg);

  registers_->irq_reg |= interruptVector;

  asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, 
            "m%s:%s: irq config register after setting interrupt vector = 0x%08x\n", 
            driverName, functionName, registers_->irq_reg);

  /* Create the thread that reads the FIFO */
  if (epicsThreadCreate("SIS3801FIFOThread",
                         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_reg);

  enableInterrupts();

  /* 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;
}
Ejemplo n.º 6
0
void drvSIS3801::startMCSAcquire()
{
  int nChans;
  int prescale;
  int channelAdvanceSource;
  int countOnStart;
  static const char *functionName="startMCSAcquire";
 
  getIntegerParam(mcaNumChannels_, &nChans);
  getIntegerParam(mcaChannelAdvanceSource_, &channelAdvanceSource);
  getIntegerParam(SIS38XXCountOnStart_, &countOnStart);
  getIntegerParam(mcaPrescale_, &prescale);
  
  setAcquireMode(ACQUIRE_MODE_MCS);
  
  // Reset the FIFO and nextSignal_, but not nextChan_ because we could be resuming acquisition
  resetFIFO();
  nextSignal_ = 0;

  if (firmwareVersion_ >= 5) {
    if (channelAdvanceSource == mcaChannelAdvance_Internal) {
        /* The SIS3801 requires the value in the LNE prescale register to be one
         * less than the actual number of incoming signals. We do this adjustment
         * here, so the user sees the actual number at the record level.
         */
        double dwellTime;
        getDoubleParam(mcaDwellTime_, &dwellTime);
        registers_->csr_reg = CONTROL_M_ENABLE_10MHZ_LNE_PRESCALER;
        prescale = (epicsUInt32) (SIS3801_10MHZ_CLOCK * dwellTime) - 1;
      }
    else if (channelAdvanceSource == mcaChannelAdvance_External) {
        getIntegerParam(mcaPrescale_, &prescale);
        /* The SIS3801 requires the value in the LNE prescale register to be one
         * less than the actual number of incoming signals. We do this adjustment
         * here, so the user sees the actual number at the record level.
         */
        prescale--;
        registers_->csr_reg = CONTROL_M_DISABLE_10MHZ_LNE_PRESCALER;
      } 
    else {
      asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, 
                "%s:%s: unsupported channel advance source %d\n", 
                driverName, functionName, channelAdvanceSource);
    }

    /* Set the prescale factor. Note, it is necessary to do the following in
     * for the prescale counter to be properly cleared:
     *  - Disable prescaler
     *  - Write prescale factor
     *  - Enable prescaler
     */
    registers_->csr_reg = CONTROL_M_DISABLE_LNE_PRESCALER;
    registers_->prescale_factor_reg = prescale;
    registers_->csr_reg = CONTROL_M_ENABLE_LNE_PRESCALER;
  }

  /* Enable next logic */
  registers_->enable_next_reg = 1;

  /* Enable counting bit in CSR */
  registers_->csr_reg = CONTROL_M_CLEAR_SOFTWARE_DISABLE;

  /* Do one software next_clock if enabled */
  if (countOnStart != 0)
    softwareChannelAdvance();
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
0
void drvSIS3820::startScaler()
{
  setAcquireMode(ACQUIRE_MODE_SCALER);
  registers_->key_op_enable_reg = 1;
}