int init_daq(double min_range, double max_range, int range_update) { int i = 0; if (!DEV_OPEN) { it = comedi_open("/dev/comedi0"); if (it == NULL) { comedi_perror("comedi_open"); ADC_OPEN = FALSE; DEV_OPEN = FALSE; return -1; } DEV_OPEN = TRUE; } subdev_ai = comedi_find_subdevice_by_type(it, COMEDI_SUBD_AI, subdev_ai); if (subdev_ai < 0) { return -2; ADC_OPEN = FALSE; } subdev_ao = comedi_find_subdevice_by_type(it, COMEDI_SUBD_AO, subdev_ao); if (subdev_ao < 0) { HAS_AO = FALSE; } else { HAS_AO = TRUE; } printf("Subdev AI %i ", subdev_ai); channels_ai = comedi_get_n_channels(it, subdev_ai); printf("Analog Channels %i ", channels_ai); maxdata_ai = comedi_get_maxdata(it, subdev_ai, i); printf("Maxdata %i ", maxdata_ai); ranges_ai = comedi_get_n_ranges(it, subdev_ai, i); printf("Ranges %i ", ranges_ai); ad_range = comedi_get_range(it, subdev_ai, i, ranges_ai - 1); if (range_update) { ad_range->min = min_range; ad_range->max = max_range; } printf(": ad_range .min = %.3f, max = %.3f\n", ad_range->min, ad_range->max); if (HAS_AO) { printf("Subdev AO %i ", subdev_ao); channels_ao = comedi_get_n_channels(it, subdev_ao); printf("Analog Channels %i ", channels_ao); maxdata_ao = comedi_get_maxdata(it, subdev_ao, i); printf("Maxdata %i ", maxdata_ao); ranges_ao = comedi_get_n_ranges(it, subdev_ao, i); printf("Ranges %i ", ranges_ao); da_range = comedi_get_range(it, subdev_ao, i, ranges_ao - 1); printf(": da_range .min = %.3f, max = %.3f\n", da_range->min, da_range->max); } ADC_OPEN = TRUE; comedi_set_global_oor_behavior(COMEDI_OOR_NUMBER); return 0; }
double readpin(int chan) { comedi_t *it; lsampl_t data, maxdata; comedi_range *rang; int readres; double outval; if((it=comedi_open("/dev/comedi0"))==NULL) { printf("fail open"); } comedi_set_global_oor_behavior(COMEDI_OOR_NUMBER); readres=comedi_data_read(it,subdev,chan,0,aref, & data); if(!readres) { comedi_perror("comedi_data_read: "); } rang = comedi_get_range(it, subdev, chan, 0); maxdata = comedi_get_maxdata(it, subdev, chan); outval = comedi_to_phys(data, rang, maxdata); printf("data=%d\noutval=%g\nreadres=%d\n",data, outval, readres); return outval; }
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { QString None(tr("Not selected")); setupUi(this); setWindowTitle(ProgramVersion); QPixmap AppIconPixmap(iconpixmap); QIcon ApplicationIcon(AppIconPixmap); setWindowIcon(ApplicationIcon); cbxAI_Im->addItem(None,0); cbxAI_Cmd->addItem(None,0); cbxAI_Cm_tlg->addItem(None,0); cbxAI_Freq_tlg->addItem(None,0); cbxAI_Gain_tlg->addItem(None,0); cbxAI_Lsw_tlg->addItem(None,0); cbxAO_Cmd->addItem(None,0); comedi_set_global_oor_behavior(COMEDI_OOR_NUMBER); GetComediInfo(); QObject::connect(btnTest, SIGNAL(clicked()), this, SLOT(RunCalibration())); QObject::connect(pbOK, SIGNAL(clicked()), this, SLOT(SaveSelections())); QObject::connect(pbReject, SIGNAL(clicked()), this, SLOT(close())); WindowUpdateTimer = new QTimer(this); connect(WindowUpdateTimer, SIGNAL(timeout()), this, SLOT(UpdateOnTimer())); WindowUpdateTimer->start(1000/WindowUpdateFrequencyHz); }
double read_volts(int subdev, int chan, int range) { lsampl_t data, maxdata; int readres; comedi_range *rang; double outval; comedi_set_global_oor_behavior(COMEDI_OOR_NUMBER); readres=comedi_data_read(it,subdev,chan,range,aref, & data); if(!readres) { comedi_perror("comedi_data_read: "); } rang = comedi_get_range(it, subdev, chan, range); maxdata = comedi_get_maxdata(it, subdev, chan); outval = comedi_to_phys(data, rang, maxdata); //printf("data=%d\noutval=%g\nreadres=%d\n",data, outval, readres); return outval; }
int init_daq(void) { int i = 0, range_index = 0; comedi_range *ad_range; if (!DEV_OPEN) { it = comedi_open(comedi_dev); if (it == NULL) { comedi_perror("comedi_open"); ADC_OPEN = FALSE; DEV_OPEN = FALSE; HAVE_DIO = FALSE; HAVE_AI = FALSE; return -1; } DEV_OPEN = TRUE; } subdev_ai = comedi_find_subdevice_by_type(it, COMEDI_SUBD_AI, subdev_ai); if (subdev_ai < 0) { return -1; ADC_OPEN = FALSE; } printf("Subdev %i ", subdev_ai); channels_ai = comedi_get_n_channels(it, subdev_ai); printf("Analog Channels %i ", channels_ai); maxdata_ai = comedi_get_maxdata(it, subdev_ai, i); printf("Maxdata %i ", maxdata_ai); ranges_ai = comedi_get_n_ranges(it, subdev_ai, i); printf("Ranges %i ", ranges_ai); for (range_index = 0; range_index < ranges_ai; range_index++) { ad_range = comedi_get_range(it, subdev_ai, i, range_index); printf(": range %i, min = %.1f, max = %.1f ", range_index, ad_range->min, ad_range->max); } printf("\n"); ADC_OPEN = TRUE; comedi_set_global_oor_behavior(COMEDI_OOR_NUMBER); return 0; }
int main() { it=comedi_open("/dev/comedi0"); int ret; if(cmd==NULL) { cmd=malloc(sizeof(*cmd)); if(cmd==NULL) return -1; } else { if(cmd->chanlist) free(cmd->chanlist); } comedi_set_global_oor_behavior(COMEDI_OOR_NUMBER); ret = prepare_cmd(COMEDI_SUBD_AI,cmd,freq); printf("B");fflush(stdout); //comedi_get_cmd_generic_timed(dev,subdevice,cmd,0,1e9/freq); if(ret<0){ printf("comedi_get_cmd_generic_timed failed\n"); return ret; } /* Modify parts of the command */ cmd->scan_end_arg = 0; cmd->stop_arg = 0; setup_read_wave(COMEDI_SUBD_AI, 0, 0, 100); ret = comedi_command(it,cmd); if(ret) printf("comedi_command (acq): %d\n", ret); internal_trigger(); comedi_cancel(it, 0); comedi_cancel(it, 1); }
/** * Start the the ADC sampling, unless the external trigger command * is set it will begin sampling as soon as the usbdux device has been * initialized. * The final three arguments are very important to get right * as the recorder thread will use them to determine where to write it's samples and * when it's reached end of the buffer. It doesn't care about the c_buffer class * at all. * @param arg_device name of the comedi device e.g., 'comedi0' * @param arg_sample_rate the rate the usb_dux should sample with in hertz (max=3[Mhz]}) * @param arg_start_address the start address of the circle buffer sample should be loading into * @param arg_end_address the end address of the cicle buffer. * @param arg_buffer_size byte size of the buffer. */ int start_Sampling(char* arg_device, uint32_t arg_sample_rate, char* arg_start_address, char* arg_end_address, int arg_buffer_size){ _channel_amount = 16; _sample_rate = arg_sample_rate; unsigned int chanlist[_channel_amount]; unsigned int convert_arg = 1e9 / _sample_rate; int ret; comedi_cmd *cmd = (comedi_cmd *) calloc(1, sizeof(comedi_cmd)); _device = comedi_open(arg_device); int buffer = 1048576*40; buffer = (buffer * 4096)/4096; if(comedi_set_max_buffer_size(_device, 0, buffer) < 0 ){ printf("Failed to set max buffer size to %i bytes\n", buffer); return -1; } else printf("Maximum buffer size set to %i bytes\n", comedi_get_max_buffer_size(_device,0)); if(comedi_set_buffer_size(_device, 0, buffer) < 0){ printf("Failed to set buffer size to %iBytes\n", buffer); return -1; } else printf("Buffer size set to %iBytes\n", comedi_get_buffer_size(_device,0)); if(!_device){ errx(1, "unable to open device"); comedi_perror("/dev/comedi0"); return -1; } for(int i = 0; i < _channel_amount; i++) chanlist[i] = i; comedi_set_global_oor_behavior(COMEDI_OOR_NUMBER); if((ret = comedi_get_cmd_generic_timed(_device, 0, cmd, _channel_amount,0)) < 0){ printf("comedi_get_cmd_generic_timed failed\n"); return ret; } cmd->chanlist = chanlist; cmd->stop_src = TRIG_NONE; cmd->stop_arg = 0; cmd->convert_arg = convert_arg; //setup the sampling to start from the trigger. //cmd->start_src = TRIG_EXT //cmd->start_arg = 1; /* call test twice because different things are tested? * if tests are successful run sampling command */ if((ret = comedi_command_test(_device, cmd)) != 0 || (ret = comedi_command_test(_device, cmd)) != 0 || (ret = comedi_command(_device, cmd)) < 0){ fprintf(stderr, "err: %d\n", ret); return -1; } FILE* dux_fp; if((dux_fp = fdopen(comedi_fileno(_device), "r")) <= 0) comedi_perror("fdopen"); char* write_address = arg_start_address; Utility::SNAP_SAMPLE = 0; Utility::LAST_SAMPLE = 0; uint64_t active_sample = 0; uint32_t tmp_block = 0; int samples_pr_block = 4096/sizeof(Type); while((ret = fread(write_address, 1, 4096,dux_fp)) >= 0){ write_address += 4096; tmp_block += 1; active_sample += samples_pr_block; Utility::LAST_SAMPLE += samples_pr_block; if(tmp_block >= Utility::SNAPSHOT_BLOCK_SIZE){ //printf("signalling serial snapshotter\n"); tmp_block = 0; Utility::SNAP_SAMPLE = active_sample; Utility::SNAP_READY = true; Utility::CV.notify_one(); } if(write_address == arg_end_address){ write_address -= arg_buffer_size; //printf("resetting to beginning of buffer\n"); } if(_stop == true) break; } if(ret < 0) perror("read"); comedi_cancel(_device, 0); return 0; }
ComediScope::ComediScope( ComediRecord *comediRecordTmp, int channels, float f, int port_for_ext_data, int maxComediDevs, int first_dev_no, int req_sampling_rate, const char* defaultTextStringForMissingExtData, int fftdevnumber, int fftchannel, int fftmaxf ) : QWidget( comediRecordTmp ) { channels_in_use = channels; tb_init=1; tb_counter=tb_init; comediRecord=comediRecordTmp; // erase plot eraseFlag = 1; fftdevno = fftdevnumber; fftch = fftchannel; fftmaxfrequency = fftmaxf; // for ASCII rec_file=NULL; // filename rec_filename=new QString(); // flag if data has been recorded and we need a new filename recorded=0; if (port_for_ext_data>0) { fprintf(stderr, "Expecting a connection on TCP port %d. \n" "Start your client now, for example: \n" "telnet localhost %d\n" "Press Ctrl-C to abort.\n", port_for_ext_data, port_for_ext_data); ext_data_receive = new Ext_data_receive( port_for_ext_data, defaultTextStringForMissingExtData ); } else { ext_data_receive = NULL; } ////////////////////////////////////////////////////////////// setAttribute(Qt::WA_OpaquePaintEvent); int range = 0; int aref = AREF_GROUND; // do not produce NAN for out of range behaviour comedi_set_global_oor_behavior(COMEDI_OOR_NUMBER); // create an array which keeps the comedi devices dev = new comedi_t*[maxComediDevs]; for(int devNo=0;devNo<maxComediDevs;devNo++) { dev[devNo] = NULL; } // let's probe how many we have nComediDevices = 0; for(int devNo=0;devNo<maxComediDevs;devNo++) { char filename[128]; sprintf(filename,"/dev/comedi%d",devNo+first_dev_no); dev[devNo] = comedi_open(filename); if(dev[devNo]){ nComediDevices = devNo + 1; } else { break; } } // none detected if (nComediDevices<1) { fprintf(stderr,"No comedi devices detected!\n"); exit(1); } // create channel lists chanlist = new unsigned int*[nComediDevices]; // create command structures cmd = new comedi_cmd*[nComediDevices]; // find the subdevice which is analogue in subdevice = comedi_find_subdevice_by_type(dev[0],COMEDI_SUBD_AI,0); // check if user has specified channels or if requested // number of channels make sense if ((channels_in_use < 1)|| (channels_in_use > comedi_get_n_channels(dev[0],subdevice))) { channels_in_use = comedi_get_n_channels(dev[0],subdevice); } // create channel lists and the command structures for(int devNo=0;devNo<nComediDevices;devNo++) { chanlist[devNo] = new unsigned int[channels_in_use]; assert( chanlist[devNo]!=NULL ); for(int i=0;i<channels_in_use;i++){ chanlist[devNo][i] = CR_PACK(i,range,aref); } cmd[devNo] = new comedi_cmd; assert( dev[devNo]!=NULL ); int r = comedi_get_cmd_generic_timed(dev[devNo], subdevice, cmd[devNo], channels_in_use, (int)(1e9/req_sampling_rate)); if(r<0){ comedi_perror("comedi_get_cmd_generic_timed failed\n"); exit(-1); } /* Modify parts of the command */ cmd[devNo]->chanlist = chanlist[devNo]; cmd[devNo]->chanlist_len = channels_in_use; cmd[devNo]->scan_end_arg = channels_in_use; cmd[devNo]->stop_src=TRIG_NONE; cmd[devNo]->stop_arg=0; int ret = comedi_command_test(dev[devNo],cmd[devNo]); if(ret<0){ comedi_perror("1st comedi_command_test failed\n"); exit(-1); } ret = comedi_command_test(dev[devNo],cmd[devNo]); if(ret<0){ comedi_perror("2nd comedi_command_test failed\n"); exit(-1); } if(ret!=0){ fprintf(stderr,"Error preparing command.\n"); exit(-1); } } // the timing is done channel by channel // this means that the actual sampling rate is divided by // number of channels if ((cmd[0]->convert_src == TRIG_TIMER)&&(cmd[0]->convert_arg)) { sampling_rate=((1E9 / cmd[0]->convert_arg)/channels_in_use); } // the timing is done scan by scan (all channels at once) // the sampling rate is equivalent of the scan_begin_arg if ((cmd[0]->scan_begin_src == TRIG_TIMER)&&(cmd[0]->scan_begin_arg)) { sampling_rate=1E9 / cmd[0]->scan_begin_arg; } // initialise the graphics stuff ypos = new int**[nComediDevices]; assert(ypos != NULL); for(int devNo=0;devNo<nComediDevices;devNo++) { ypos[devNo]=new int*[channels_in_use]; assert(ypos[devNo] != NULL); for(int i=0;i<channels_in_use;i++) { ypos[devNo][i] = new int[MAX_DISP_X]; assert( ypos[devNo][i] != NULL); for(int j=0;j<MAX_DISP_X;j++) { ypos[devNo][i][j]=0; } } } xpos=0; nsamples=0; maxdata = new lsampl_t[nComediDevices]; assert( maxdata != NULL ); crange = new comedi_range*[nComediDevices]; assert( crange != NULL ); for(int devNo=0;devNo<nComediDevices;devNo++) { // we just go for the default ranges maxdata[devNo]=comedi_get_maxdata(dev[devNo],subdevice,0); crange[devNo]=comedi_get_range(dev[devNo],subdevice,0,0); } // 50Hz or 60Hz mains notch filter iirnotch = new Iir::Butterworth::BandStop<IIRORDER>**[nComediDevices]; assert( iirnotch != NULL ); adAvgBuffer = new float*[nComediDevices]; assert( adAvgBuffer != NULL ); daqData = new lsampl_t*[nComediDevices]; assert( daqData != NULL ); for(int devNo=0;devNo<nComediDevices;devNo++) { iirnotch[devNo] = new Iir::Butterworth::BandStop<IIRORDER>*[channels_in_use]; assert( iirnotch[devNo] != NULL ); // floating point buffer for plotting adAvgBuffer[devNo]=new float[channels_in_use]; assert( adAvgBuffer[devNo] != NULL ); for(int i=0;i<channels_in_use;i++) { adAvgBuffer[devNo][i]=0; iirnotch[devNo][i] = new Iir::Butterworth::BandStop<IIRORDER>; assert( iirnotch[devNo][i] != NULL ); } // raw data buffer for saving the data daqData[devNo] = new lsampl_t[channels_in_use]; assert( daqData[devNo] != NULL ); for(int i=0;i<channels_in_use;i++) { daqData[devNo][i]=0; } } setNotchFrequency(f); counter = new QTimer( this ); assert( counter != NULL ); connect( counter, SIGNAL(timeout()), this, SLOT(updateTime()) ); }
static PyObject* comediModule(PyObject* self, PyObject* args) { char *device; int subdevice; int channel; int range; int aref; int n_chan; int n_scan; float freq; if (!PyArg_ParseTuple(args, "siiiiiif", &device, &subdevice, &channel, &range, &aref, &n_chan, &n_scan, &freq)) return NULL; comedi_t *dev; comedi_cmd c,*cmd=&c; int ret; int total=0; int i; struct timeval start,end; int subdev_flags; lsampl_t raw; struct parsed_options options; init_parsed_options(&options); options.filename = device; options.subdevice = subdevice; options.channel = channel; options.range = range; options.aref = aref; options.n_chan = n_chan; options.n_scan = n_scan; options.freq = freq; /* open the device */ dev = comedi_open(options.filename); if(!dev){ comedi_perror(options.filename); exit(1); } // Print numbers for clipped inputs comedi_set_global_oor_behavior(COMEDI_OOR_NUMBER); /* Set up channel list */ for(i = 0; i < options.n_chan; i++){ chanlist[i] = CR_PACK(options.channel + i, options.range, options.aref); range_info[i] = comedi_get_range(dev, options.subdevice, options.channel, options.range); maxdata[i] = comedi_get_maxdata(dev, options.subdevice, options.channel); } prepare_cmd_lib(dev, options.subdevice, options.n_scan, options.n_chan, 1e9 / options.freq, cmd); fprintf(stderr, "command before testing:\n"); dump_cmd(stderr, cmd); ret = comedi_command_test(dev, cmd); if(ret < 0){ comedi_perror("comedi_command_test"); if(errno == EIO){ fprintf(stderr,"Ummm... this subdevice doesn't support commands\n"); } exit(1); } fprintf(stderr,"first test returned %d (%s)\n", ret, cmdtest_messages[ret]); dump_cmd(stderr, cmd); ret = comedi_command_test(dev, cmd); if(ret < 0){ comedi_perror("comedi_command_test"); exit(1); } fprintf(stderr,"second test returned %d (%s)\n", ret, cmdtest_messages[ret]); if(ret!=0){ dump_cmd(stderr, cmd); fprintf(stderr, "Error preparing command\n"); exit(1); } /* this is only for informational purposes */ gettimeofday(&start, NULL); fprintf(stderr,"start time: %ld.%06ld\n", start.tv_sec, start.tv_usec); /* start the command */ ret = comedi_command(dev, cmd); if(ret < 0){ comedi_perror("comedi_command"); exit(1); } subdev_flags = comedi_get_subdevice_flags(dev, options.subdevice); const int ndim = 2; npy_intp nd[2] = {n_scan, n_chan}; PyObject *myarray; double *array_buffer; myarray = PyArray_SimpleNew(ndim, nd, NPY_DOUBLE); Py_INCREF(myarray); array_buffer = (double *)PyArray_DATA(myarray); while(1){ ret = read(comedi_fileno(dev),buf,BUFSZ); if(ret < 0){ /* some error occurred */ perror("read"); break; }else if(ret == 0){ /* reached stop condition */ break; }else{ static int col = 0; double j = 0.0; int bytes_per_sample; total += ret; if(options.verbose)fprintf(stderr, "read %d %d\n", ret, total); if(subdev_flags & SDF_LSAMPL) bytes_per_sample = sizeof(lsampl_t); else bytes_per_sample = sizeof(sampl_t); for(i = 0; i < ret / bytes_per_sample; i++){ if(subdev_flags & SDF_LSAMPL) { raw = ((lsampl_t *)buf)[i]; } else { raw = ((sampl_t *)buf)[i]; } *array_buffer++ = print_datum(raw, col, 1); col++; if(col == options.n_chan){ col=0; j++; printf("\n"); } } } } /* this is only for informational purposes */ gettimeofday(&end,NULL); fprintf(stderr,"end time: %ld.%06ld\n", end.tv_sec, end.tv_usec); end.tv_sec -= start.tv_sec; if(end.tv_usec < start.tv_usec){ end.tv_sec--; end.tv_usec += 1000000; } end.tv_usec -= start.tv_usec; fprintf(stderr,"time: %ld.%06ld\n", end.tv_sec, end.tv_usec); return myarray; }
int main(int argc, char *argv[]) { comedi_t *dev; comedi_cmd c,*cmd=&c; int ret; int total=0; int i; struct timeval start,end; int subdev_flags; lsampl_t raw; struct parsed_options options; init_parsed_options(&options); parse_options(&options, argc, argv); /* The following variables used in this demo * can be modified by command line * options. When modifying this demo, you may want to * change them here. */ options.filename = "/dev/comedi0"; options.subdevice = 0; options.channel = 0; options.range = 6; options.aref = AREF_DIFF; options.n_chan = 8; options.n_scan = 100000; options.freq = 1000.0; options.physical = 1; /* open the device */ dev = comedi_open(options.filename); if(!dev){ comedi_perror(options.filename); exit(1); } // Print numbers for clipped inputs comedi_set_global_oor_behavior(COMEDI_OOR_NUMBER); /* Set up channel list */ //for(i = 0; i < options.n_chan/2; i++){ for(i = 0; i < options.n_chan; i++){ chanlist[i] = CR_PACK(options.channel + i, options.range, options.aref); range_info[i] = comedi_get_range(dev, options.subdevice, options.channel, options.range); maxdata[i] = comedi_get_maxdata(dev, options.subdevice, options.channel); } /* for(i = options.n_chan/2; i < options.n_chan; i++){ fprintf(stderr,"%d: %d\n", i, options.channel + i + 8); chanlist[i] = CR_PACK(options.channel + i + 8, options.range, options.aref); range_info[i] = comedi_get_range(dev, options.subdevice, options.channel, options.range); maxdata[i] = comedi_get_maxdata(dev, options.subdevice, options.channel); } */ /* prepare_cmd_lib() uses a Comedilib routine to find a * good command for the device. prepare_cmd() explicitly * creates a command, which may not work for your device. */ prepare_cmd_lib(dev, options.subdevice, options.n_scan, options.n_chan, 1e9 / options.freq, cmd); //prepare_cmd(dev, options.subdevice, options.n_scan, options.n_chan, 1e9 / options.freq, cmd); fprintf(stderr, "command:\n"); dump_cmd(stderr, cmd); /* this is only for informational purposes */ gettimeofday(&start, NULL); fprintf(stderr,"start time: %ld.%06ld\n", start.tv_sec, start.tv_usec); /* start the command */ ret = comedi_command(dev, cmd); if(ret < 0){ comedi_perror("comedi_command"); exit(1); } subdev_flags = comedi_get_subdevice_flags(dev, options.subdevice); while(1){ ret = read(comedi_fileno(dev),buf,BUFSZ); if(ret < 0){ /* some error occurred */ perror("read"); continue; }else if(ret == 0){ /* reached stop condition */ break; }else{ static int col = 0; int bytes_per_sample; total += ret; if(options.verbose)fprintf(stderr, "read %d %d\n", ret, total); if(subdev_flags & SDF_LSAMPL) bytes_per_sample = sizeof(lsampl_t); else bytes_per_sample = sizeof(sampl_t); for(i = 0; i < ret / bytes_per_sample; i++){ if(subdev_flags & SDF_LSAMPL) { raw = ((lsampl_t *)buf)[i]; } else { raw = ((sampl_t *)buf)[i]; } print_datum(raw, col, options.physical); col++; if(col == options.n_chan){ printf("\n"); col=0; } } } } /* this is only for informational purposes */ gettimeofday(&end,NULL); fprintf(stderr,"end time: %ld.%06ld\n", end.tv_sec, end.tv_usec); end.tv_sec -= start.tv_sec; if(end.tv_usec < start.tv_usec){ end.tv_sec--; end.tv_usec += 1000000; } end.tv_usec -= start.tv_usec; fprintf(stderr,"time: %ld.%06ld\n", end.tv_sec, end.tv_usec); return 0; }
MainWindow::MainWindow( QWidget *parent ) : QWidget(parent), adChannel(0), psthLength(1000), psthBinw(20), spikeThres(1), psthOn(0), spikeDetected(false), time(0), linearAverage(0) { // initialize comedi const char *filename = "/dev/comedi0"; /* open the device */ if( (dev = comedi_open(filename)) == 0 ) { comedi_perror(filename); exit(1); } // do not produce NAN for out of range behaviour comedi_set_global_oor_behavior(COMEDI_OOR_NUMBER); maxdata = comedi_get_maxdata(dev, COMEDI_SUB_DEVICE, 0); crange = comedi_get_range(dev,COMEDI_SUB_DEVICE,0,0); numChannels = comedi_get_n_channels(dev, COMEDI_SUB_DEVICE); chanlist = new unsigned[numChannels]; /* Set up channel list */ for( int i=0; i<numChannels; i++ ) chanlist[i] = CR_PACK(i, COMEDI_RANGE_ID, AREF_GROUND); int ret = comedi_get_cmd_generic_timed( dev, COMEDI_SUB_DEVICE, &comediCommand, numChannels, (int)(1e9/(SAMPLING_RATE)) ); if(ret < 0) { printf("comedi_get_cmd_generic_timed failed\n"); exit(-1); } /* Modify parts of the command */ comediCommand.chanlist = chanlist; comediCommand.stop_src = TRIG_NONE; comediCommand.stop_arg = 0; /* comedi_command_test() tests a command to see if the * trigger sources and arguments are valid for the subdevice. * If a trigger source is invalid, it will be logically ANDed * with valid values (trigger sources are actually bitmasks), * which may or may not result in a valid trigger source. * If an argument is invalid, it will be adjusted to the * nearest valid value. In this way, for many commands, you * can test it multiple times until it passes. Typically, * if you can't get a valid command in two tests, the original * command wasn't specified very well. */ ret = comedi_command_test(dev, &comediCommand); if(ret < 0) { comedi_perror("comedi_command_test"); exit(-1); } fprintf(stderr, "first test returned %d\n", ret); ret = comedi_command_test(dev, &comediCommand); if(ret < 0) { comedi_perror("comedi_command_test"); exit(-1); } fprintf(stderr, "second test returned %d\n", ret); if(ret != 0) { fprintf(stderr,"Error preparing command\n"); exit(-1); } // the timing is done channel by channel // this means that the actual sampling rate is divided by // number of channels if ((comediCommand.convert_src == TRIG_TIMER)&&(comediCommand.convert_arg)) { sampling_rate=(((double)1E9 / comediCommand.convert_arg)/numChannels); } // the timing is done scan by scan (all channels at once) // the sampling rate is equivalent of the scan_begin_arg if ((comediCommand.scan_begin_src == TRIG_TIMER)&&(comediCommand.scan_begin_arg)) { sampling_rate=(double)1E9 / comediCommand.scan_begin_arg; } // 50Hz or 60Hz mains notch filter iirnotch = new Iir::Butterworth::BandStop<IIRORDER>; assert( iirnotch != NULL ); iirnotch->setup (IIRORDER, sampling_rate, NOTCH_F, NOTCH_F/10.0); /* start the command */ ret = comedi_command(dev, &comediCommand); if(ret < 0) { comedi_perror("comedi_command"); exit(1); } int subdev_flags = comedi_get_subdevice_flags(dev, COMEDI_SUB_DEVICE); if( (sigmaBoard = subdev_flags & SDF_LSAMPL) ) readSize = sizeof(lsampl_t) * numChannels; else readSize = sizeof(sampl_t) * numChannels; // Initialize data for plots for(int i=0; i<MAX_PSTH_LENGTH; i++) { xData[i] = i; // time axis yData[i] = 0; timeData[i] = double(i)*psthBinw; // psth time axis spikeCountData[i] = 0; psthData[i] = 0; } // the gui, straight forward QT/Qwt resize(640,420); QHBoxLayout *mainLayout = new QHBoxLayout( this ); QVBoxLayout *controlLayout = new QVBoxLayout; mainLayout->addLayout(controlLayout); QVBoxLayout *plotLayout = new QVBoxLayout; plotLayout->addStrut(400); mainLayout->addLayout(plotLayout); // two plots RawDataPlot = new DataPlot(xData, yData, psthLength, crange->max, crange->min, this); plotLayout->addWidget(RawDataPlot); RawDataPlot->show(); plotLayout->addSpacing(20); MyPsthPlot = new PsthPlot(timeData, psthData, psthLength/psthBinw, this); plotLayout->addWidget(MyPsthPlot); MyPsthPlot->show(); /*---- Buttons ----*/ // AD group QGroupBox *ADcounterGroup = new QGroupBox( "A/D Channel", this ); QVBoxLayout *ADcounterLayout = new QVBoxLayout; ADcounterGroup->setLayout(ADcounterLayout); ADcounterGroup->setAlignment(Qt::AlignJustify); ADcounterGroup->setSizePolicy( QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed) ); controlLayout->addWidget( ADcounterGroup ); QwtCounter *cntChannel = new QwtCounter(ADcounterGroup); cntChannel->setRange(0, numChannels-1, 1); cntChannel->setValue(adChannel); ADcounterLayout->addWidget(cntChannel); connect(cntChannel, SIGNAL(valueChanged(double)), SLOT(slotSetChannel(double))); filter50HzCheckBox = new QCheckBox( "50Hz filter" ); filter50HzCheckBox->setEnabled( true ); ADcounterLayout->addWidget(filter50HzCheckBox); // psth functions QGroupBox *PSTHfunGroup = new QGroupBox( "Actions", this ); QVBoxLayout *PSTHfunLayout = new QVBoxLayout; PSTHfunGroup->setLayout(PSTHfunLayout); PSTHfunGroup->setAlignment(Qt::AlignJustify); PSTHfunGroup->setSizePolicy( QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed) ); controlLayout->addWidget( PSTHfunGroup ); averagePsth = new QComboBox(PSTHfunGroup); averagePsth->addItem(tr("PSTH")); averagePsth->addItem(tr("VEP")); PSTHfunLayout->addWidget(averagePsth); connect( averagePsth, SIGNAL(currentIndexChanged(int)), SLOT(slotAveragePsth(int)) ); triggerPsth = new QPushButton(PSTHfunGroup); triggerPsth->setText("PSTH on"); triggerPsth->setCheckable(true); PSTHfunLayout->addWidget(triggerPsth); connect(triggerPsth, SIGNAL(clicked()), SLOT(slotTriggerPsth())); QPushButton *clearPsth = new QPushButton(PSTHfunGroup); clearPsth->setText("clear data"); PSTHfunLayout->addWidget(clearPsth); connect(clearPsth, SIGNAL(clicked()), SLOT(slotClearPsth())); QPushButton *savePsth = new QPushButton(PSTHfunGroup); savePsth->setText("save data"); PSTHfunLayout->addWidget(savePsth); connect(savePsth, SIGNAL(clicked()), SLOT(slotSavePsth())); // psth params QGroupBox *PSTHcounterGroup = new QGroupBox( "Parameters", this ); QVBoxLayout *PSTHcounterLayout = new QVBoxLayout; PSTHcounterGroup->setLayout(PSTHcounterLayout); PSTHcounterGroup->setAlignment(Qt::AlignJustify); PSTHcounterGroup->setSizePolicy( QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed) ); controlLayout->addWidget( PSTHcounterGroup ); QLabel *psthLengthLabel = new QLabel("Sweep length", PSTHcounterGroup); PSTHcounterLayout->addWidget(psthLengthLabel); QwtCounter *cntSLength = new QwtCounter(PSTHcounterGroup); cntSLength->setNumButtons(2); cntSLength->setIncSteps(QwtCounter::Button1, 10); cntSLength->setIncSteps(QwtCounter::Button2, 100); cntSLength->setRange(1, MAX_PSTH_LENGTH, 1); cntSLength->setValue(psthLength); PSTHcounterLayout->addWidget(cntSLength); connect(cntSLength, SIGNAL(valueChanged(double)), SLOT(slotSetPsthLength(double))); QLabel *binwidthLabel = new QLabel("Binwidth", PSTHcounterGroup); PSTHcounterLayout->addWidget(binwidthLabel); cntBinw = new QwtCounter(PSTHcounterGroup); cntBinw->setNumButtons(2); cntBinw->setIncSteps(QwtCounter::Button1, 1); cntBinw->setIncSteps(QwtCounter::Button2, 10); cntBinw->setRange(1, 100, 1); cntBinw->setValue(psthBinw); PSTHcounterLayout->addWidget(cntBinw); connect(cntBinw, SIGNAL(valueChanged(double)), SLOT(slotSetPsthBinw(double))); QLabel *thresholdLabel = new QLabel("Spike Threshold", PSTHcounterGroup); PSTHcounterLayout->addWidget(thresholdLabel); editSpikeT = new QTextEdit("0"); QFont editFont("Courier",14); QFontMetrics editMetrics(editFont); editSpikeT->setMaximumHeight ( editMetrics.height()*1.2 ); editSpikeT->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); editSpikeT->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); editSpikeT->setFont(editFont); PSTHcounterLayout->addWidget(editSpikeT); connect(editSpikeT, SIGNAL(textChanged()), SLOT(slotSetSpikeThres())); thresholdMarker = new QwtPlotMarker(); thresholdMarker->setValue(0,0); thresholdMarker->attach(RawDataPlot); thresholdMarker->setLineStyle(QwtPlotMarker::HLine); // Generate timer event every 50ms (void)startTimer(50); }
int32 ATIDAQHardwareInterface::ConfigSingleSampleTask( float64 sampleRate, int averaging, const std::string & deviceName, int firstChannel, int numChannels, int minVoltage, int maxVoltage ) { int32 retVal = 0; /*the return value <0 is err >0 is warning, 0 ok*/ /*we have to use unmanaged c-style strings in here because that's what the NI-DAQmx C Library uses*/ char channelString[WHOLE_LOTTA_CHARACTERS]; /*the channel string, of format "Dev1/ai0:5"*/ /*set up member data*/ m_f64SamplingFrequency = sampleRate; m_uiAveragingSize = ( averaging > 0 )? averaging : 1; /*averaging must be at least 1*/ m_sDeviceName = deviceName; m_uiFirstChannel = firstChannel; m_uiNumChannels = numChannels; //for this we are using bipolar so do the reverse... // if ( m_Calibration->BiPolar ) // { // m_iMinVoltage += ( m_Calibration->VoltageRange / 2 ); // m_dLowerSaturationVoltage = m_iMinVoltage * GAUGE_SATURATION_LEVEL; // m_iMaxVoltage += ( m_Calibration->VoltageRange / 2 ); // m_dUpperSaturationVoltage = m_iMaxVoltage * GAUGE_SATURATION_LEVEL; // } // //make sure the out of range is returned as a number comedi_set_global_oor_behavior(COMEDI_OOR_NUMBER); m_iMinVoltage = minVoltage; m_iMaxVoltage = maxVoltage; range.max= m_iMaxVoltage; range.min= m_iMinVoltage; range.unit = UNIT_volt; // comediDev = comedi_open(m_sDeviceName.c_str()); //error; if (comediDev == NULL) { comedi_perror(m_sDeviceName.c_str()); return -1; } maxdata = comedi_get_maxdata(comediDev, 0,0); //create an instruction set to grab readings one by one. insn = new comedi_insn[m_uiNumChannels]; dataArray = new lsampl_t[m_uiNumChannels]; /* Set up a the "instruction list", which is just a pointer * to the array of instructions and the number of instructions. */ il.n_insns = m_uiNumChannels; il.insns = insn; for (int chan = 0 ; chan < m_uiNumChannels ; chan ++){ /* Instruction 1: do 10 analog input reads */ insn[chan].insn = INSN_READ; insn[chan].n = 1; insn[chan].data = &(dataArray[chan]); insn[chan].subdev = 0; insn[chan].chanspec = CR_PACK(chan,0,AREF_DIFF); } // unsigned int numSamplesPerChannel = m_uiAveragingSize; /*the number of samples per channel that daqmx is configured with*/ // /*in a perfect world, NI-DAQmx would allow us to set up single scan acquisitions, but they don't. // even if we were to make the single sample task a finite sample task, they still require you to use // at least 2 samples per channel. Therefore, we pass daqmx a number of samples per channel that it // will accept, and then set up our task to only read the most recent samples*/ // if ( MIN_SAMPLES_PER_CHANNEL > numSamplesPerChannel ) numSamplesPerChannel = MIN_SAMPLES_PER_CHANNEL; // // ati_Channel_Name_Format( channelString, m_sDeviceName ); /* Format the channel name for niDAQmx */ // // /*if the following confuses you, I suggest you read the NI-DAQmx C Reference Help, included // with NI-DAQmx*/ // StopCollection(); /*stop currently running task*/ // /*if any function fails (returns non-zero), don't execute any more daqmx functions*/ // /*create the daqmx task*/ // if( !( retVal = DAQmxCreateTask( "", m_thDAQTask ) ) ) // /*add the analog input channels to the task - july.22.2005 - ss - now uses m_iConnectionMode*/ // if( !( retVal = DAQmxCreateAIVoltageChan( *m_thDAQTask, channelString, "", m_iConnectionMode, // m_iMinVoltage, m_iMaxVoltage, DAQmx_Val_Volts, NULL ) ) ) // /*set up timing for the task*/ // if( !( retVal = DAQmxCfgSampClkTiming( *m_thDAQTask, NULL, m_f64SamplingFrequency, // DAQmx_Val_Rising, DAQmx_Val_ContSamps, numSamplesPerChannel ) ) ) // /*set read position relative to next sample to be read*/ // if( !( retVal = DAQmxSetReadRelativeTo( *m_thDAQTask, DAQmx_Val_MostRecentSamp ) ) ) // /*offset of -1 from the next sample, meaning we read the most recent sample*/ // if( !( retVal = DAQmxSetReadOffset( *m_thDAQTask, 0 ) ) ) // /*start the task*/ // retVal = DAQmxStartTask( *m_thDAQTask ); return retVal; }