void drvSIS3801::resetScaler() { //static const char *functionName="resetScaler"; setAcquireMode(ACQUIRE_MODE_SCALER); resetFIFO(); nextChan_ = 0; nextSignal_ = 0; }
void drvSIS3820::resetScaler() { /* Reset scaler */ setAcquireMode(ACQUIRE_MODE_SCALER); registers_->key_op_disable_reg = 1; resetFIFO(); registers_->key_counter_clear = 1; }
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_); }
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; } }
/*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 **)®isters_); 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 *) ®isters_->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; }
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(); }
/** 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, ¶mName); 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; }
/*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 **)®isters_); 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, ®isters_->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; }
void drvSIS3820::startScaler() { setAcquireMode(ACQUIRE_MODE_SCALER); registers_->key_op_enable_reg = 1; }