/* ************************************************************************** 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(exp)); state* a_state=(state*)si.get_state(); /* loop over all states */ while (NULL!=a_state) { // collect analogin sections in state std::list inputs; /* loop over all device definitions in a state */ state::iterator i=a_state->begin(); while (i!=a_state->end()) { analogin* input=dynamic_cast(*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"); }