234 lines
7.4 KiB
C++
234 lines
7.4 KiB
C++
/* **************************************************************************
|
|
|
|
Author: Achim Gaedke
|
|
Created: June 2004
|
|
|
|
****************************************************************************/
|
|
#include "core/core.h"
|
|
#include "Datel-PCI416.h"
|
|
|
|
DatelPCI416::DatelPCI416(const ttlout& t_line){
|
|
trigger_line=t_line;
|
|
PCI_DLL = LoadLibrary("PCI41632");
|
|
if (PCI_DLL==NULL) {
|
|
throw ADC_exception("found no library\n");
|
|
}
|
|
|
|
/* import all functions from dll and exit on error*/
|
|
# define pci41632dll_getproc(name) \
|
|
name = (TFP_ ## name)GetProcAddress(PCI_DLL,#name); \
|
|
if (name == NULL) {FreeLibrary(PCI_DLL); throw ADC_exception("found no " #name " function in DLL");}
|
|
# include "PCI416_func_import.cpp"
|
|
|
|
if (pci416_init(&brdcount)!=NOERROR) {
|
|
brdcount=0;
|
|
throw ADC_exception("initialisation failed");
|
|
}
|
|
|
|
// now hardcoded, use first board
|
|
board=0;
|
|
if (NOERROR!=pci416_getcaps(board,4,caps))
|
|
throw ADC_exception("getcaps failed");
|
|
fprintf(stderr,"Datel PCI416 caps: FIFO size: %d, DMA size: %d, index ADM %d, acqmode %d\n",caps[0],caps[1],caps[2],caps[3]);
|
|
|
|
sample_count=0;
|
|
trigger_count=0;
|
|
sample_frequency=0;
|
|
|
|
trigger_line.ttls=1<<2;
|
|
trigger_line.id=0;
|
|
|
|
}
|
|
|
|
DatelPCI416::~DatelPCI416() {
|
|
pci416_close(board);
|
|
FreeLibrary(PCI_DLL);
|
|
}
|
|
|
|
/**
|
|
here the data aquisition unit is configured and adds the necessary pusle components to the program
|
|
*/
|
|
void DatelPCI416::set_daq(state& exp) {
|
|
|
|
sample_count=0;
|
|
trigger_count=0;
|
|
sample_frequency=0;
|
|
|
|
// todo: cleanup before exception...
|
|
state_iterator si(dynamic_cast<state_sequent&>(exp));
|
|
state* a_state=(state*)si.get_state();
|
|
/* loop over all states */
|
|
while (NULL!=a_state) {
|
|
// collect analogin sections in state
|
|
std::list<analogin*> inputs;
|
|
/* loop over all device definitions in a state */
|
|
state::iterator i=a_state->begin();
|
|
while (i!=a_state->end()) {
|
|
analogin* input=dynamic_cast<analogin*>(*i);
|
|
if (input!=NULL) {
|
|
/* collect appropiate analogin sections, forget others */
|
|
if (input->samples<=0 || input->sample_frequency<=0)
|
|
delete input;
|
|
else
|
|
inputs.push_back(input);
|
|
i=a_state->erase(i);
|
|
}
|
|
else
|
|
++i;
|
|
}
|
|
if (!inputs.empty()) {
|
|
/* evaluate the found analogin definitions */
|
|
if (inputs.size()>1) {
|
|
while (!inputs.empty()) {delete inputs.front(); inputs.pop_front();}
|
|
throw ADC_exception("can not handle more than one analogin section per state");
|
|
}
|
|
if (trigger_count==0) {
|
|
sample_count=inputs.front()->samples;
|
|
sample_frequency=inputs.front()->sample_frequency;
|
|
trigger_count=si.get_count();
|
|
}
|
|
else if ( sample_count==inputs.front()->samples && sample_frequency==inputs.front()->sample_frequency ) {
|
|
trigger_count+=si.get_count();
|
|
}
|
|
else {
|
|
while (!inputs.empty()) {delete inputs.front(); inputs.pop_front();}
|
|
throw ADC_exception("Sorry, but multittriggering requires same parameters in all analogin sections");
|
|
}
|
|
|
|
if (a_state->length<1.0*sample_count/sample_frequency) {
|
|
fprintf(stderr,"WARINING: state is shorter than aquisition time\n");
|
|
}
|
|
a_state->push_back(trigger_line.copy_new());
|
|
|
|
// to do: more analogin sections per state
|
|
while (!inputs.empty()) {delete inputs.front(); inputs.pop_front();}
|
|
}
|
|
// send a trigger pulse
|
|
// todo only short trigger pulse
|
|
a_state=(state*)si.next_state();
|
|
}
|
|
|
|
/* nothing to do! */
|
|
if (trigger_count==0 || sample_count==0) return;
|
|
|
|
|
|
if (sample_count*trigger_count*4>caps[1])
|
|
throw ADC_exception("required dma buffer size is too big for pci slot config");
|
|
fprintf(stderr,"samples: %d, triggers: %d, frequency=%f\n", sample_count, trigger_count, sample_frequency);
|
|
|
|
/* initialise board */
|
|
if (NOERROR!=set_modes(board,
|
|
0, // clock source: 0=internal
|
|
sample_frequency, // sample rate
|
|
sample_count*2, // samples per trigger
|
|
1, // trigger src: 0=internal, 1=external digital
|
|
1, // channel (1= Ch1 and Ch2)
|
|
0, // pretrigger
|
|
1, // scan (multichannel=1)
|
|
0 // marker
|
|
))
|
|
throw ADC_exception("set_modes failed...");
|
|
|
|
// clear fifo, even when using dma
|
|
if (NOERROR!=pci416_clear_fifo(board)) throw ADC_exception("clear_fifo failed");
|
|
|
|
DWORD dma_buffer_size[2];
|
|
dma_buffer_size[0]=dma_buffer_size[1]=sample_count*trigger_count*4; //bytes
|
|
dma_buffer_handle=0;
|
|
if (NOERROR!=pci416_setup_dma(board,DMA_SINGLE,dma_buffer_size,&dma_buffer_handle))
|
|
throw ADC_exception("setup_dma failed");
|
|
|
|
// start single aquisition
|
|
double freq=1.0;
|
|
// start_daq(board, trigger_mode, frequency) trigger mode: 0 external
|
|
if (NOERROR!=start_daq(board,0,&freq)) throw ADC_exception("start_daq failed");
|
|
|
|
}
|
|
|
|
adc_result* DatelPCI416::get_samples(double timeout) {
|
|
// nothing to do here
|
|
if (trigger_count==0 || sample_count==0) return new adc_result(1,0,NULL);
|
|
|
|
const size_t poll_time=10000;
|
|
double time_spent=0;
|
|
// busy wait for end
|
|
fprintf(stderr,"waiting for ADC");
|
|
while (core::term_signal==0) {
|
|
DWORD dma_status=0;
|
|
// status NOT DONE=0, Done=1
|
|
if (pci416_dma_status(board,&dma_status)!=NOERROR)
|
|
throw ADC_exception("dma_status failed");
|
|
if (dma_status!=0) break;
|
|
usleep(poll_time);
|
|
time_spent+=1e-6*poll_time;
|
|
fprintf(stderr,".",dma_status);
|
|
fflush(stderr);
|
|
if (time_spent>timeout) {
|
|
fprintf(stderr," timeout!\n");
|
|
throw ADC_exception("ran into timeout!");
|
|
}
|
|
}
|
|
fprintf(stderr," done\n");
|
|
if (core::term_signal!=0) return NULL;
|
|
|
|
if (NOERROR!=stop_daq(board))
|
|
throw ADC_exception("stop daq failed");
|
|
if(NOERROR!=pci416_stop_dma(board,NULL))
|
|
throw ADC_exception("stop_dma failed");
|
|
|
|
// copy results...
|
|
DWORD resulting_bytes=sample_count*trigger_count*4; // bytes
|
|
short int* data=(short int*)malloc(resulting_bytes);
|
|
if (data==NULL) throw ADC_exception("Could not allocate enough memory");
|
|
if (NOERROR!=pci416_copy_dmabuffer(board, DMA_SINGLE, 0, &resulting_bytes, (DWORD*)data)) {
|
|
free(data);
|
|
throw ADC_exception("copy_dmabuffer failed");
|
|
}
|
|
|
|
#if 0
|
|
fprintf(stderr,"got %d bytes back\n",resulting_bytes);
|
|
FILE* binfile=fopen("/tmp/bla.bin","w+");
|
|
if (binfile!=NULL) {
|
|
fwrite(data,1,resulting_bytes, binfile);
|
|
fclose(binfile);
|
|
}
|
|
else
|
|
fprintf(stderr,"could not open file\n");
|
|
#endif
|
|
/* return them */
|
|
return new adc_result(1, sample_count*trigger_count, data, sample_frequency);
|
|
}
|
|
|
|
|
|
void DatelPCI416::sample_after_external_trigger(const double rate, const size_t samples, double sensitivity, size_t resolution) {
|
|
const int board=0;
|
|
|
|
// try dma
|
|
if (NOERROR!=set_modes(board,
|
|
0, // clock source: 0=internal
|
|
rate, // sample rate
|
|
samples*2, // samples per trigger
|
|
1, // trigger src: 0=internal, external digital =1
|
|
1, // channel (1= Ch1 and Ch2)
|
|
0, // pretrigger
|
|
1, // scan
|
|
0 // marker
|
|
))
|
|
throw ADC_exception("set_modes failed...");
|
|
|
|
// clear fifo, even when using dma
|
|
if (NOERROR!=pci416_clear_fifo(board)) throw ADC_exception("clear_fifo failed");
|
|
|
|
DWORD dma_buffer_size[2];
|
|
dma_buffer_size[0]=dma_buffer_size[1]=samples*trigger_count*4; //bytes
|
|
DWORD dma_buffer_handle=0;
|
|
if (NOERROR!=pci416_setup_dma(board,DMA_SINGLE,dma_buffer_size,&dma_buffer_handle))
|
|
throw ADC_exception("setup_dma failed");
|
|
fprintf(stderr,"buffersize %d\n",dma_buffer_size[0]);
|
|
|
|
// start single aquisition
|
|
double freq=1.0;
|
|
if (NOERROR!=start_daq(board,0,&freq)) throw ADC_exception("start_daq failed");
|
|
}
|
|
|