278 lines
7.5 KiB
C
278 lines
7.5 KiB
C
|
// todo: Multi-Platform support is not implemented.
|
||
|
// todo: fifo if needed
|
||
|
|
||
|
|
||
|
#ifndef SPECTRUM_M2i40XXSERIES
|
||
|
#define SPECTRUM_M2i40XXSERIES
|
||
|
|
||
|
#define SPCM_MAX_AIRANGE 8
|
||
|
#define SPCM_MAX_AICHANNEL 16
|
||
|
|
||
|
#include <string>
|
||
|
#include <vector>
|
||
|
#include <math.h>
|
||
|
#include "core/states.h"
|
||
|
#include "core/constants.h"
|
||
|
#include "drivers/ADC.h"
|
||
|
#include "GatedData.h"
|
||
|
|
||
|
#if defined __linux__
|
||
|
// ----- linux includes -----
|
||
|
# include <cstdio>
|
||
|
# include <fcntl.h>
|
||
|
# include <sys/ioctl.h>
|
||
|
# include <unistd.h>
|
||
|
# include "include/dlltyp.h"
|
||
|
# include "include/regs.h"
|
||
|
# include "include/spcerr.h"
|
||
|
# include "include/spcm_drv.h"
|
||
|
#endif
|
||
|
|
||
|
#if !(defined __linux__)
|
||
|
# error "sorry, expecting linux"
|
||
|
#endif
|
||
|
|
||
|
#ifndef SPC_DEBUG
|
||
|
# define SPC_DEBUG 0
|
||
|
#endif
|
||
|
|
||
|
/**
|
||
|
\defgroup spectrum2i40xxseries Spectrum M2i40xx ADC
|
||
|
\ingroup drivers
|
||
|
\brief The driver for the Spectrum M2i.40xx series analog to digital converter.
|
||
|
|
||
|
The M2i.4021/4022 we use supports sampling with up to 20 MS/s on 2/4 channels. This driver requires the GatedSampling option to be installed.
|
||
|
@{
|
||
|
*/
|
||
|
|
||
|
class SpectrumM2i40xxSeries_error: public ADC_exception
|
||
|
{
|
||
|
public:
|
||
|
explicit SpectrumM2i40xxSeries_error(const std::string& msg) throw (): ADC_exception(msg) {}
|
||
|
explicit SpectrumM2i40xxSeries_error(const char* msg) throw (): ADC_exception(msg) {}
|
||
|
virtual ~SpectrumM2i40xxSeries_error() throw () {}
|
||
|
protected:
|
||
|
virtual const std::string prefix() const { return "ERROR (SpectrumM2i40xxSeries_error): "; }
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
\brief The driver class
|
||
|
*/
|
||
|
class SpectrumM2i40xxSeries: public ADC {
|
||
|
|
||
|
/**
|
||
|
ttlout triggerline device id
|
||
|
*/
|
||
|
int device_id;
|
||
|
/**
|
||
|
ttlout triggerline ttlmask
|
||
|
*/
|
||
|
ttlout trigger_line;
|
||
|
|
||
|
/** stuff concerning fifo acquisition */
|
||
|
size_t fifobufferno;
|
||
|
/** stuff concerning fifo acquisition */
|
||
|
size_t fifobufferlen;
|
||
|
/** stuff concerning fifo acquisition */
|
||
|
size_t fifo_minimal_size;
|
||
|
/** stuff concerning fifo acquisition */
|
||
|
std::vector<short int*> fifobuffers;
|
||
|
/** the extra data thread should store things to that buffer */
|
||
|
short int* fifo_adc_data;
|
||
|
pthread_attr_t timeout_pt_attrs;
|
||
|
pthread_t timeout_pt;
|
||
|
|
||
|
|
||
|
# if defined __linux__
|
||
|
// ----- include the easy ioctl commands from the driver -----
|
||
|
# include "include/spcioctl.inc"
|
||
|
# endif
|
||
|
|
||
|
/**
|
||
|
\brief Stores card settings and information
|
||
|
*/
|
||
|
class Configuration {
|
||
|
public:
|
||
|
/** sampling frequency in Hz */
|
||
|
double samplefreq;
|
||
|
/** Data returned by the ADC during the different gating periods is stored in a nested list */
|
||
|
DataManagementNode* data_structure;
|
||
|
/** a timeout for acquiring data in s*/
|
||
|
double timeout;
|
||
|
/** configured input impedance for each channel in Ohm*/
|
||
|
double* impedance;
|
||
|
/** configured input sensitivity for each channel in V*/
|
||
|
double* sensitivity;
|
||
|
/** coupling 0=DC else AC */
|
||
|
int coupling;
|
||
|
/** external reference clock **/
|
||
|
int ext_reference_clock;
|
||
|
/** offsets for each channel in % of sensitivity **/
|
||
|
int* offset;
|
||
|
|
||
|
// Information about the card copied from the Spectrum example program
|
||
|
|
||
|
/** \brief The card's driver handle as returned by the Spectrum driver open function */
|
||
|
drv_handle hDrv;
|
||
|
/** \brief The card's ID
|
||
|
* Typically 0 if no other card is installed. The device is created as /dev/spcm0
|
||
|
*/
|
||
|
int32 lCardID;
|
||
|
|
||
|
/** \brief The card's type as listed in the manual */
|
||
|
int32 lCardType;
|
||
|
/** \brief Serial Number */
|
||
|
int32 lSerialNumber;
|
||
|
/** \brief Installed on-board memory in bytes */
|
||
|
int64 llInstMemBytes;
|
||
|
/** \brief Bitmap with installed card features */
|
||
|
int32 lFeatureMap;
|
||
|
/** \brief Number of channels (analog or digital) */
|
||
|
int32 lMaxChannels;
|
||
|
/** \brief Number of bytes for each sample (analog data) */
|
||
|
int32 lBytesPerSample;
|
||
|
/** \brief Minimum sampling rate */
|
||
|
int32 lMinSampleRate;
|
||
|
/** \brief Maximum sampling rate */
|
||
|
int32 lMaxSampleRate;
|
||
|
/** \brief Number of installed modules for data sorting algorithm */
|
||
|
int32 lModulesCount;
|
||
|
|
||
|
/** \brief Library version */
|
||
|
int32 lLibVersion;
|
||
|
/** \brief Kernel version */
|
||
|
int32 lKernelVersion;
|
||
|
|
||
|
/** \brief Main control firmware version */
|
||
|
int32 lCtrlFwVersion;
|
||
|
/** \brief Base hardware version */
|
||
|
int32 lBaseHwVersion;
|
||
|
/** \brief Module hardware version */
|
||
|
int32 lModHwVersion;
|
||
|
/** \brief Module firmware version */
|
||
|
int32 lModFwVersion;
|
||
|
|
||
|
|
||
|
// current settings
|
||
|
/** \brief Bitmap for currently enabled channels */
|
||
|
channel_array qwSetChEnableMap;
|
||
|
/** \brief Programmed memory size */
|
||
|
int llSetMemsize;
|
||
|
/** \brief Number of used channels for this run */
|
||
|
int lSetChannels;
|
||
|
/** \brief Currently active oversampling factor */
|
||
|
int32 lOversampling;
|
||
|
|
||
|
|
||
|
// Analog Input settings
|
||
|
/** \brief Resolution of analog input channel */
|
||
|
int32 lResolution;
|
||
|
int32 lMaxADCValue; // maximum range, normally 2^(Resolution-1) but can be limited
|
||
|
int32 lPathCount; // number of input paths
|
||
|
int32 lRangeCount; // number of analog input ranges
|
||
|
int32 lRangeMin[SPCM_MAX_AIRANGE]; // analog input ranges
|
||
|
int32 lRangeMax[SPCM_MAX_AIRANGE]; // ...
|
||
|
bool bInputTermAvailable; // input termination available
|
||
|
bool bDiffModeAvailable; // differential mode available
|
||
|
bool bACCouplingAvailable; // AC/DC coupling softwar selectable
|
||
|
bool bBWLimitAvailable; // bandwidth limit available
|
||
|
bool bOffsPercentMode; // offset programmed in percent of range
|
||
|
|
||
|
|
||
|
|
||
|
/** print data for debug purpose */
|
||
|
void print(FILE* f);
|
||
|
|
||
|
bool bOpenCard();
|
||
|
char* PrintInfo();
|
||
|
|
||
|
Configuration() {
|
||
|
samplefreq=0;
|
||
|
timeout=0;
|
||
|
impedance = NULL;
|
||
|
sensitivity = NULL;
|
||
|
offset = NULL;
|
||
|
coupling=0;
|
||
|
ext_reference_clock=0;
|
||
|
data_structure=NULL;
|
||
|
hDrv = NULL;
|
||
|
|
||
|
lCardID = 0;
|
||
|
lSetChannels = 0;
|
||
|
lBytesPerSample = 0;
|
||
|
}
|
||
|
|
||
|
Configuration(const Configuration& orig) {
|
||
|
samplefreq=orig.samplefreq;
|
||
|
timeout=orig.timeout;
|
||
|
impedance=orig.impedance;
|
||
|
sensitivity=orig.sensitivity;
|
||
|
coupling=orig.coupling;
|
||
|
ext_reference_clock=orig.ext_reference_clock;
|
||
|
qwSetChEnableMap = orig.qwSetChEnableMap;
|
||
|
lSetChannels = orig.lSetChannels;
|
||
|
if (orig.data_structure==NULL)
|
||
|
data_structure=NULL;
|
||
|
else
|
||
|
data_structure=new DataManagementNode(*orig.data_structure);
|
||
|
}
|
||
|
|
||
|
~Configuration() {
|
||
|
if (data_structure!=NULL)
|
||
|
delete data_structure;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
\brief Default settings for the ADC card.
|
||
|
These settings are copied and modified at need to derive effective settings
|
||
|
*/
|
||
|
Configuration default_settings;
|
||
|
|
||
|
/**
|
||
|
\brief The settings actually used for a measurement.
|
||
|
Once a measurement is started, user settings may override default settings
|
||
|
*/
|
||
|
Configuration* effective_settings;
|
||
|
|
||
|
short int* split_adcdata_recursive(short int* data, const DataManagementNode& structure, adc_results& result_splitted);
|
||
|
|
||
|
/**
|
||
|
\brief Collects the settings required for the current job.
|
||
|
*/
|
||
|
void collect_config_recursive(state_sequent& exp, SpectrumM2i40xxSeries::Configuration& settings);
|
||
|
|
||
|
public:
|
||
|
|
||
|
SpectrumM2i40xxSeries(const ttlout& t_line, int ext_reference_clock=(int)100e6);
|
||
|
|
||
|
virtual void sample_after_external_trigger(double rate, size_t samples, double sensitivity=5.0, size_t resolution=14);
|
||
|
|
||
|
virtual void set_daq(state & exp);
|
||
|
|
||
|
|
||
|
/**
|
||
|
for syncronization purposes with sample clock
|
||
|
*/
|
||
|
//double get_sample_clock_frequency() const;
|
||
|
|
||
|
/**
|
||
|
get results from transient recorder
|
||
|
timeout: 0.0 return immediately
|
||
|
*/
|
||
|
virtual result* get_samples(double timeout=0.0);
|
||
|
|
||
|
/**
|
||
|
timeout issues during fifo acquisition
|
||
|
*/
|
||
|
//int TimeoutThread();
|
||
|
|
||
|
virtual ~SpectrumM2i40xxSeries();
|
||
|
};
|
||
|
|
||
|
/** @{
|
||
|
*/
|
||
|
|
||
|
#endif
|