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; }
ComediChan::ComediChan(comedi_t *dev, unsigned minor, unsigned subdev, unsigned chan, unsigned range, unsigned aref, const double * range_override_min, const double * range_override_max, DAQTaskProxy *daq) : m_dev(dev), m_minor(minor), m_subdev(subdev), m_chan(chan), m_range(range), m_aref(aref), daq(daq) { m_isdio = m_isai = m_isao = false; int t = comedi_get_subdevice_type(m_dev, m_subdev); if (t == COMEDI_SUBD_AO) m_isao = true; else if (t == COMEDI_SUBD_AI) m_isai = true; else if (t == COMEDI_SUBD_DIO) m_isdio = true; else { err = "Invalid parameters."; return; } if (range_override_min) m_rangeMin = *range_override_min; else { comedi_range *r = comedi_get_range(dev, subdev, chan, range); if (!r) { err = "Invalid parameters."; return; } m_rangeMin = r->unit == UNIT_mA ? r->min*1e3 : r->min; } if (range_override_max) m_rangeMax = *range_override_max; else { comedi_range *r = comedi_get_range(dev, subdev, chan, range); if (!r) { err = "Invalid parameters."; return; } m_rangeMax = r->unit == UNIT_mA ? r->max*1e3 : r->max; } m_maxdata = comedi_get_maxdata(dev, subdev, chan); if (!m_maxdata) m_maxdata = 1; err = ""; }
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; }
/** * @brief AIO_channel Constructor * @param dname Device name * @param sd subdevice * @param ch channel * @param rng range * @param input true if it's input channel * @param uID channel unique ID */ AIO_channel(QString dname,int sd,int ch, int rng, int input, int uID) { deviceName=dname;subdevice =sd; Channel=ch; is_input=input;ChannelID=uID; rangeN=rng; range = comedi_get_range(it,subdevice, Channel,rangeN); maxdata = comedi_get_maxdata(it, subdevice,Channel); }
/** * @brief constructor from the ini file * * @param keyname Ini file keyword * @param input true if it is an input channel */ AIO_channel(QString keyname, int input) { read_fromIni(keyname, &deviceName, &subdevice, &Channel, &rangeN); range = comedi_get_range(it,subdevice, Channel,rangeN); maxdata = comedi_get_maxdata(it, subdevice,Channel); is_input=input; }
ComediAnalogOutputSoftCal::ComediAnalogOutputSoftCal(const char *deviceFile, uint outputSubdevice, uint writeChannel, double outputConversionFactor, uint aref, bool resetOutput) : ComediAnalogIOSoftCal(deviceFile, outputSubdevice, &writeChannel, 1, PLUS_MINUS_TEN, aref), m_outputConversionFactor(outputConversionFactor), m_resetOutput(resetOutput) { Logger(Debug, "ComediAnalogOutputSoftCal::ComediAnalogOutputSoftCal()\n"); int flag = comedi_get_softcal_converter(m_subdevice, m_channels[0], m_range, COMEDI_FROM_PHYSICAL, m_calibration, &m_converter); if (flag != 0) { Logger(Critical, "comedi_get_softcal_converter: %s.\n", comedi_strerror(comedi_errno())); throw "Error in comedi_get_softcal_converter()"; } #ifdef TRIM_ANALOG_OUTPUT // get physical data range for subdevice (min, max, phys. units) m_dataRange = comedi_get_range(m_device, m_subdevice, m_channels[0], m_range); Logger(Debug, "Range for 0x%x (%s):\n\tmin = %g\n\tmax = %g\n", m_dataRange, (m_dataRange->unit == UNIT_volt ? "volts" : "milliamps"), m_dataRange->min, m_dataRange->max); if(m_dataRange == NULL) { Logger(Critical, "comedi_get_range: %s.\n", comedi_strerror(comedi_errno())); throw "Error in comedi_get_range()"; } #endif }
double get_adc_volts(int chan, int diff, int range) { lsampl_t data[OVER_SAMPLE]; // adc burst data buffer int retval; comedi_range *ad_range; comedi_insn daq_insn; ADC_ERROR = FALSE; // global fault flag if (diff == TRUE) { aref_ai = AREF_DIFF; } else { aref_ai = AREF_GROUND; } // configure the AI channel for reads daq_insn.subdev = subdev_ai; daq_insn.chanspec = CR_PACK(chan, range, aref_ai); daq_insn.insn = INSN_READ; daq_insn.n = OVER_SAMPLE; daq_insn.data = data; retval = comedi_do_insn(it, &daq_insn); // send one instruction to the driver if (retval < 0) { comedi_perror("comedi_do_insn in get_adc_volts"); ADC_ERROR = TRUE; bmc.raw[chan] = 0; return 0.0; } ad_range = comedi_get_range(it, subdev_ai, chan, range); bmc.raw[chan] = data[0]; return comedi_to_phys(data[0], ad_range, maxdata_ai); // return the double result }
bool ComediAnalogOutputHardCal::initialise() { // get physical data range for subdevice (min, max, phys. units) m_dataRange = comedi_get_range(m_device, m_subdevice, m_channels[0], m_range); Logger(Debug, "Range for 0x%x (%s):\n\tmin = %g\n\tmax = %g\n", m_dataRange, (m_dataRange->unit == UNIT_volt ? "volts" : "milliamps"), m_dataRange->min, m_dataRange->max); if(m_dataRange == NULL) { comedi_perror(m_deviceFile); comedi_close(m_device); return false; } // read max data value m_maxData = comedi_get_maxdata(m_device, m_subdevice, m_channels[0]); Logger(Debug, "Max data = %ld\n", m_maxData); }
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 setup_read_wave(int subd, int chan, int range, int npnts) { // assert(it!=NULL); printf("setup_read_wave...");fflush(stdout); int ret; int wv_n=++cmd->chanlist_len, wv_i=wv_n-1; lsampl_t data; //printf("wv_i %d \n", wv_i); ///assert(cmd!=NULL); if(cmd->chanlist==NULL) { cmd->chanlist=malloc(sizeof(unsigned int)); } else { if(realloc(cmd->chanlist, (wv_n)*sizeof(unsigned int))==NULL) { printf("realloc cmd fail \n"); return -1;} } cmd->chanlist[wv_i]= CR_PACK(chan,range,aref); if(npnts>cmd->stop_arg) cmd->stop_arg=npnts; cmd->scan_end_arg=wv_n; //test_board_read(it); comedi_command_test(it,cmd); ret=comedi_command_test(it,cmd); if(ret!=0){ comedi_perror("comedi_command_test fail on read"); return -1; } //test_board_read(it); inp_res[wv_i]=malloc(npnts*sizeof(double)); inp_rang[wv_i]=comedi_get_range(it, subd, chan, range); inp_maxdata[wv_i]=comedi_get_maxdata(it, subd, chan); comedi_data_read(it,subd,chan,range,aref, & data); //printf("found sdtype %d \n", comedi_find_subdevice_by_type(it, COMEDI_SUBD_AI,0)); //printf("setup subd %d chan %d rng %d: data=%d outval=%g\n",subd, chan, range, data, comedi_to_phys(data, inp_rang[wv_i], inp_maxdata[wv_i])); printf("done\n");fflush(stdout); return wv_i; }
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; }
/** * facq_comedi_misc_get_min: * @dev: A comedi_t device. * @subindex: The subdevice index. * @chanlist: A #FacqChanlist object. * @err: A #GError. * * It's equal to facq_comedi_misc_get_max() but instead of returning the * maximum values, returns the minimum expected real values. * * Returns: A gdouble array. Free it with g_free(): */ gdouble *facq_comedi_misc_get_min(comedi_t *dev,guint subindex,const FacqChanlist *chanlist,GError **err) { guint iochans_n = 0, i = 0, chanspec = 0, chan = 0,range = 0; GError *local_err = NULL; gdouble *min = NULL; comedi_range *rng = NULL; g_return_val_if_fail(FACQ_IS_CHANLIST(chanlist),NULL); iochans_n = facq_chanlist_get_io_chans_n(chanlist); if(!iochans_n){ g_set_error_literal(&local_err, FACQ_COMEDI_MISC_ERROR, FACQ_COMEDI_MISC_ERROR_FAILED, "The chanlist is empty"); goto error; } min = g_new0(gdouble,iochans_n); for(i = 0;i < iochans_n;i++){ chanspec = facq_chanlist_get_io_chanspec(chanlist,i); facq_chanlist_chanspec_to_src_values(chanspec,&chan, &range,NULL,NULL); rng = comedi_get_range(dev,subindex,chan,range); if(!rng){ g_set_error_literal(&local_err, FACQ_COMEDI_MISC_ERROR, FACQ_COMEDI_MISC_ERROR_FAILED, comedi_strerror(comedi_errno())); } min[i] = rng->min; } return min; error: if(min) g_free(min); if(local_err) g_propagate_error(err,local_err); return NULL; }
double get_adc_volts(int chan, int diff, int range) { lsampl_t data[OVER_SAMPLE]; // adc burst data buffer int retval, intg, i; comedi_range *ad_range; comedi_insn daq_insn; ADC_ERROR = FALSE; // global fault flag if (diff == TRUE) { aref_ai = AREF_DIFF; } else { aref_ai = AREF_GROUND; } intg = 0; // clear the integration counter // configure the AI channel for burst reads of OVER_SAMPLE times with the passed params daq_insn.subdev = subdev_ai; daq_insn.chanspec = CR_PACK(chan, range, aref_ai); daq_insn.insn = INSN_READ; daq_insn.n = OVER_SAMPLE; daq_insn.data = data; retval = comedi_do_insn(it, &daq_insn); // send one instruction to the driver if (retval < 0) { comedi_perror("comedi_do_insn in get_adc_volts"); ADC_ERROR = TRUE; bmc.raw[chan] = 0; return 0.0; } for (i = 0; i < OVER_SAMPLE; i++) { intg += data[i]; } data[0] = intg >> OVER_SAMPLE_SHIFTS; ad_range = comedi_get_range(it, subdev_ai, chan, range); bmc.raw[chan] = data[0]; return comedi_to_phys(data[0], ad_range, ((1 << (OVER_SAMPLE_ADC + OVER_SAMPLE_BITS)) - 1)); // return the double result }
void print_card_info(comedi_t *card) { //We get the number of ranges for this card int n_ranges; int chan=1; n_ranges=comedi_get_n_ranges( card, SUBDEV, chan); printf("This card have %d ranges\n",n_ranges); int i; //We display information about these ranges comedi_range *act_range; for(i=0;i<n_ranges;i++) { act_range=comedi_get_range( card, SUBDEV, chan,i); printf("range %d\t min %f\t max %f\t unit: %s\n",i,act_range->min,act_range->max,display_unit(act_range->unit)); } //We get the maxdata int maxdata; maxdata=comedi_get_maxdata(card,SUBDEV,chan); printf("maximum data value %d\n",maxdata); }
/* -------------------------------------------------------------------- */ static long dsetWrite_devAoSyncComedi(aoRecord *pao) { CONTEXT *p_myContext; COMEDIDEV_AO *p_myAnalogOutput; double myMinimumVoltage; double myMaximumVoltage; char p_myWarmstartFilename[BUFLEN]; FILE *p_myFileHandle; dsetLog(3,__FILE__ "[%d] -> %s(%s)\n", __LINE__, __func__,pao->name); pao->pact=TRUE; p_myContext=(CONTEXT *)pao->dpvt; p_myAnalogOutput=p_myContext->p_analogOutput; myMaximumVoltage=p_myContext->maximumVoltage; myMinimumVoltage=p_myContext->minimumVoltage; if (pao->val>pao->drvh) pao->val=pao->drvh; if (pao->val<pao->drvl) pao->val=pao->drvl; umask(0000); sprintf(p_myWarmstartFilename, WARMSTART_FILE_PREFIX "/%s", pao->name); p_myFileHandle=fopen(p_myWarmstartFilename,"w"); if (p_myFileHandle==NULL) { dsetLog(1, __FILE__ "[%d] Error: %s\n", __LINE__, pao->name); dsetLog(1, __FILE__ "[%d] Error: Couldn't open file >%s<\n", __LINE__, p_myWarmstartFilename); sleep(SLEEPTIME_ERROR); return(ERROR); } fprintf(p_myFileHandle,"%lg",pao->val); fclose(p_myFileHandle); if (pao->drvh!=myMaximumVoltage || pao->drvl!=myMinimumVoltage) { p_myAnalogOutput->range=getOptimalOperatingRange(pao); p_myAnalogOutput->c_range=comedi_get_range(p_myAnalogOutput->device, p_myAnalogOutput->subdevice, p_myAnalogOutput->channel, p_myAnalogOutput->range); } p_myAnalogOutput->data=comedi_from_phys( pao->val, p_myAnalogOutput->c_range, p_myAnalogOutput->maxdata); dsetLog(7, __FILE__ "[%d] Synchronous write of a single value\n", __LINE__); if( comedi_data_write( p_myAnalogOutput->device, p_myAnalogOutput->subdevice, p_myAnalogOutput->channel, p_myAnalogOutput->range, p_myAnalogOutput->aref, p_myAnalogOutput->data) <= ERROR ) { comedi_perror(p_myAnalogOutput->p_deviceFilename); sleep(SLEEPTIME_ERROR); return(ERROR); } dsetLog(2,__FILE__ "[%d] %s -> %lg\n", __LINE__, pao->name, pao->val); pao->pact=FALSE; dsetLog(3, __FILE__ "[%d] <- %s\n", __LINE__, __func__ ); /* CONVERT according to calibration settings */ return(CONVERT); }
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); }
/** * @brief Get the information from Comedi library * */ void MainWindow::GetComediInfo() { int i,j; int n_subdevices,type; int chan,n_chans; int n_ranges; int subdev_flags; comedi_range *rng; ChannelList.clear(); // at the moment we are using the default device const char optionsfilename[]="/dev/comedi0"; QString DeviceName=AppSettings.value(Key_Comedi_Device_Name).toString(); if (DeviceName.length()<=0) DeviceName=optionsfilename; it = comedi_open(optionsfilename); if(!it) { QMessageBox::warning(this, optionsfilename, tr("Can not open the device\n"), QMessageBox::Ok); }; cbComediDevice->addItem(optionsfilename,1); AppSettings.setValue(Key_Comedi_Device_Name,DeviceName); QString buffer="Overall info:\n"; //buffer+=QString printf(" Version code: 0x%06x\n", comedi_get_version_code(it)); buffer+=QString(" Comedi version code: 0x%06x\n").arg(comedi_get_version_code(it)); buffer+=QString(" Driver name: %1\n").arg(comedi_get_driver_name(it)); buffer+=QString(" Board name: %1\n").arg(comedi_get_board_name(it)); n_subdevices = comedi_get_n_subdevices(it); buffer+=QString(" Number of subdevices: %1\n").arg(n_subdevices); tlComediInfo->setText(buffer); int channel_unique_id=1; // Now scan subdevices for(i = 0; i < n_subdevices; i++) { buffer.clear(); type = comedi_get_subdevice_type(it, i); if(type==COMEDI_SUBD_UNUSED) continue; QTextEdit * tabText=new QTextEdit; buffer+=QString("Subdevice %1\n").arg(i); buffer+=QString("Type: %1 (%2)\n").arg(type).arg(subdevice_types[type]); subdev_flags = comedi_get_subdevice_flags(it, i); QString flagsstring; flagsstring.sprintf("flags: 0x%08x\n",subdev_flags); buffer+=flagsstring; n_chans=comedi_get_n_channels(it,i); buffer+=QString(" Number of channels: %1\n").arg(n_chans); if ((type==1)||(type==2)) // Analog input or output { for(chan=0;chan<n_chans;chan++) { // here! ChannelList.append(AIO_channel(QString(optionsfilename),i,chan,0,type==1,++channel_unique_id)); }; }; if(!comedi_maxdata_is_chan_specific(it,i)) { buffer+=QString(" Maximal data value: %1\n").arg((unsigned long)comedi_get_maxdata(it,i,0)); } else { buffer+=QString(" Maximal data value is channel specific:\n"); for(chan=0;chan<n_chans;chan++) { buffer+=QString(" Channel %1: %2\n").arg(chan).arg ((unsigned long)comedi_get_maxdata(it,i,chan)); } }; buffer+=QString(" ranges:\n"); if (!comedi_range_is_chan_specific(it,i)) { n_ranges=comedi_get_n_ranges(it,i,0); buffer+=QString(" All channels:"); for(j=0;j<n_ranges;j++) { rng=comedi_get_range(it,i,0,j); // buffer+=QString(" [%g,%g]",rng->min,rng->max); buffer+=QString(" [%1,%2]").arg(rng->min).arg(rng->max); } buffer+=QString("\n"); } else { for (chan=0;chan<n_chans;chan++) { n_ranges=comedi_get_n_ranges(it,i,chan); printf(" chan%d:",chan); for(j=0;j<n_ranges;j++) { rng=comedi_get_range(it,i,chan,j); printf(" [%g,%g]",rng->min,rng->max); } printf("\n"); } } tabText->setText(buffer); tabWidget->addTab(tabText,QString("subdevice %1").arg(i)); } //printf(" command:\n"); //get_command_stuff(it,i); tabWidget->setTabText(0,tr("Connections")); // Create channles we might need; all are input channels save one Ini_ImI= new AIO_channel(Key_Im_Input,1); Ini_CmdI= new AIO_channel(Key_Cmd_Input,1); Ini_CmI= new AIO_channel(Key_Cm_Tlgf_Input,1); Ini_GainT= new AIO_channel(Key_Gain_Tlgf_Input,1); Ini_FreqT= new AIO_channel(Key_Freq_Tlgf_Input,1); Ini_LswT= new AIO_channel(Key_Lsw_Tlgf_Input,1); Ini_CmdO= new AIO_channel(Key_Cmd_Output,0); for (int ch=0;ch<ChannelList.count();ch++) { if (ChannelList[ch].is_input) { cbxAI_Im->addItem(ChannelList[ch].Description(),ChannelList[ch].ID()); if (ChannelList[ch]==Ini_ImI) { int zzz=cbxAI_Im->count(); cbxAI_Im->setCurrentIndex(zzz-1); }; cbxAI_Cmd->addItem(ChannelList[ch].Description(),ChannelList[ch].ID()); if (ChannelList[ch]==Ini_CmdI) { cbxAI_Cmd->setCurrentIndex(cbxAI_Cmd->count()-1); }; cbxAI_Cm_tlg->addItem(ChannelList[ch].Description(),ChannelList[ch].ID()); if (ChannelList[ch]==Ini_CmI) { cbxAI_Cm_tlg->setCurrentIndex(cbxAI_Cm_tlg->count()-1); }; cbxAI_Gain_tlg->addItem(ChannelList[ch].Description(),ChannelList[ch].ID()); if (ChannelList[ch]==Ini_GainT){ cbxAI_Gain_tlg->setCurrentIndex(cbxAI_Gain_tlg->count()-1); }; cbxAI_Freq_tlg->addItem(ChannelList[ch].Description(),ChannelList[ch].ID()); if (ChannelList[ch]==Ini_FreqT) { cbxAI_Freq_tlg->setCurrentIndex(cbxAI_Freq_tlg->count()-1); }; cbxAI_Lsw_tlg->addItem(ChannelList[ch].Description(),ChannelList[ch].ID()); if (ChannelList[ch]==Ini_LswT) { cbxAI_Lsw_tlg->setCurrentIndex(cbxAI_Lsw_tlg->count()-1); }; } else { cbxAO_Cmd->addItem(ChannelList[ch].Description(),ChannelList[ch].ID()); if (ChannelList[ch]==Ini_CmdO) { cbxAO_Cmd->setCurrentIndex(cbxAO_Cmd->count()-1); }; }; }; return; }
bogio_spec *bogio_open(bogio_spec *spec) { unsigned int *chanlist; /* For Comedi channel flags */ unsigned int osr; /* Oversampling rate */ int i; /* Maybe the caller didn't have a bogio_spec */ if (spec == NULL) { spec = calloc(1U, sizeof(bogio_spec)); /* We have to set these here because 0 is a valid argument */ spec->subdevice = 0U; spec->range = 0U; /* +/- 4V */ spec->aref = AREF_GROUND; } /* Set defaults if the caller didn't supply parameters */ if (spec->comedi_device == NULL) spec->comedi_device = "/dev/comedi0"; if (spec->sample_rate == 0) spec->sample_rate = 1000; /* 1kHz default sample rate */ if (spec->channels == 0) spec->channels = 8; /* 8 input channels by default */ /* implied: oversampling = 0 (no oversampling) */ /* Reserve memory for the Comedi command */ spec->m_cmd = calloc(1, sizeof(comedi_cmd)); /* Try to open the device */ spec->m_dev = comedi_open(spec->comedi_device); if (spec->m_dev == NULL){ comedi_perror(spec->comedi_device); return NULL; } /* Calculate the oversampled rate for the target sample rate */ spec->oversampling = 0; /* To do! */ osr = spec->oversampling ? spec->oversampling : 1; osr *= (1000000000U/spec->sample_rate); /* That's 1e9 */ /* Set up channel list */ chanlist = (unsigned int *)calloc(spec->channels, sizeof(unsigned int)); for(i=0 ; i < spec->channels ; i++) chanlist[i]=CR_PACK(i, spec->range, spec->aref); i = comedi_get_cmd_generic_timed(spec->m_dev, spec->subdevice, spec->m_cmd, spec->channels, osr ); if (i < 0) { fprintf(stderr, "comedi_get_cmd_generic_timed failed\n"); return NULL; } /* Modify parts of the command */ spec->m_cmd->chanlist = chanlist; spec->m_cmd->chanlist_len = spec->channels; spec->m_cmd->scan_end_arg = spec->channels; spec->m_cmd->stop_src = TRIG_NONE; spec->m_cmd->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. */ i = comedi_command_test(spec->m_dev, spec->m_cmd); if (i < 0) { comedi_perror("comedi_command_test -- first attempt"); exit(-1); } /* fprintf(stderr,"first test returned %d\n",i); */ i = comedi_command_test(spec->m_dev, spec->m_cmd); if (i < 0){ comedi_perror("comedi_command_test -- second attempt"); return NULL; } /* fprintf(stderr,"second test returned %d\n",i); */ if (i != 0){ fprintf(stderr,"Error preparing command\n"); return NULL; } /* Make sure the sample rate wasn't modified */ if (spec->m_cmd->convert_src==TRIG_TIMER && spec->m_cmd->convert_arg) spec->sample_rate = 1E9/spec->m_cmd->convert_arg; if (spec->m_cmd->scan_begin_src==TRIG_TIMER && spec->m_cmd->scan_begin_arg) spec->sample_rate = 1E9/spec->m_cmd->scan_begin_arg; /* start the command */ i = comedi_command(spec->m_dev, spec->m_cmd); if (i < 0) { comedi_perror("comedi_command"); return NULL; } /* That worked: report the current settings */ /* Read the maxdata value and range for each channel; it will be used later for normalisation */ spec->m_max_sample = calloc(spec->channels, sizeof(lsampl_t)); spec->fsd = calloc(spec->channels, sizeof(comedi_range *)); for (i = 0 ; i < spec->channels ; i++) { spec->m_max_sample[i] = comedi_get_maxdata(spec->m_dev, spec->subdevice, i); spec->fsd[i] = comedi_get_range(spec->m_dev, spec->subdevice, i, spec->range); } return spec; }
/* -------------------------------------------------------------------- */ static long dsetRead_devAiSyncComedi(aiRecord *pai) { CONTEXT *p_myContext; int mySubdevice; int myChannel; int myRange = 0; int myAnalogReference; int myPinNumber; char p_myDeviceFile[BUFLEN]; comedi_t *p_myComediFileHandle; lsampl_t data; int maxdata; int ret; dsetLog(3, __FILE__ "[%d] -> %s(%s)\n", __LINE__, __func__, pai->name ); p_myContext = pai->dpvt; p_myComediFileHandle = p_myContext->p_comediFileHandle; myChannel = p_myContext->channel; myRange = p_myContext->range; myAnalogReference = p_myContext->analogReference; mySubdevice = p_myContext->subdevice; myPinNumber = p_myContext->pinNumber; strcpy(p_myDeviceFile, p_myContext->p_deviceFile); #if 0 dsetLog(7,__FILE__ "[%d] Subdevice = %d PinNumber =%d\n", __LINE__, mySubdevice, myPinNumber); dsetLog(7,__FILE__ "[%d] AnalogReference = %d Channel=%d\n", __LINE__, myAnalogReference, myChannel); dsetLog(7, __FILE__ "[%d] -> Range is %d\n", __LINE__, myRange); #endif maxdata = comedi_get_maxdata(p_myComediFileHandle, mySubdevice, myChannel); #if 0 dsetLog(7,__FILE__ "[%d] maxdata = %d pn=%d\n", __LINE__, maxdata, myPinNumber); dsetLog(7,__FILE__ "[%d] Data %d -> device %s\n", __LINE__, data, pai->name); dsetLog(7,__FILE__ "[%d] New Range = %lg\n", comedi_get_range(p_myComediFileHandle, mySubdevice, myChannel, myRange)); #endif ret = comedi_data_read(p_myComediFileHandle, mySubdevice, myChannel, myRange, myAnalogReference, &data); if (ret < 0) { comedi_perror(p_myDeviceFile); dsetLog(1, __FILE__ "[%d] Error: Couldn't read hardware\n", __LINE__); sleep(SLEEPTIME_ERROR); return(ERROR); } pai->val = comedi_to_phys(data, comedi_get_range(p_myComediFileHandle, mySubdevice, myChannel, myRange), maxdata); pai->udf = isnan(pai->val); dsetLog(7,__FILE__ "[%d] pai->udf is %d \n", __LINE__, pai->udf); if (pai->udf) { pai->val = 10; dsetLog(7,__FILE__ "[%d] Error: Cable is disconnected, please verify\n", __LINE__); } dsetLog(7,__FILE__ "[%d] val,rval=%lg,%d -> %s\n", __LINE__, pai->val, pai->rval, pai->name); dsetLog(3,__FILE__ "[%d] <- %s\n", __LINE__, __func__); return(NO_AUTOMATIC_CONVERSION); /*return(DO_AUTOMATIC_CONVERSION); */ }
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; }
int main(int argc, char *argv[]) { comedi_cmd cmd; int err; int n, m, k; comedi_t *dev; unsigned int chanlist[100]; unsigned int maxdata; comedi_range *rng; int ret; struct parsed_options options; int fn = 256*256; sampl_t *data, *dp; float v; init_parsed_options(&options); options.subdevice = -1; options.n_chan = 100000;/* default number of samples */ parse_options(&options, argc, argv); dev = comedi_open( options.filename ); if(dev == NULL){ fprintf(stderr, "error opening %s\n", options.filename); return -1; } if(options.subdevice < 0) options.subdevice = comedi_find_subdevice_by_type(dev, COMEDI_SUBD_AI, 0); maxdata = comedi_get_maxdata(dev, options.subdevice, options.channel); rng = comedi_get_range(dev, options.subdevice, options.channel, options.range); memset(&cmd,0,sizeof(cmd)); /* cmd.subdev = options.subdevice; cmd.flags = 0; cmd.start_src = TRIG_INT; cmd.start_arg = 0; cmd.scan_begin_src = TRIG_TIMER; cmd.scan_begin_arg = 1e9 / options.freq; cmd.convert_src = TRIG_TIMER; cmd.convert_arg = 1e9 / options.freq / 50; cmd.scan_end_src = TRIG_COUNT; cmd.scan_end_arg = options.n_chan; cmd.stop_src = TRIG_COUNT; cmd.stop_arg = fn; cmd.stop_src = TRIG_NONE; cmd.stop_arg = 0; */ cmd.scan_begin_src = TRIG_TIMER; cmd.flags = TRIG_ROUND_NEAREST; err = comedi_get_cmd_generic_timed( dev, options.subdevice, &cmd, options.n_chan, 1e9 / options.freq ); cmd.start_src = TRIG_INT; cmd.start_arg = 0; cmd.scan_end_arg = options.n_chan; cmd.stop_src = TRIG_NONE; cmd.stop_arg = 0; cmd.chanlist = chanlist; cmd.chanlist_len = options.n_chan; for ( k=0; k<options.n_chan; k++ ) chanlist[k] = CR_PACK(k, options.range, options.aref); dump_cmd(stderr,&cmd); if ( cmd.scan_begin_arg > 1e9 / options.freq ) { fprintf( stderr, "frequency too high! Maximum possible is %g Hz\n", 1.0e9/cmd.scan_begin_arg ); comedi_close( dev ); return 1; } err = comedi_command_test(dev, &cmd); if (err > 0 && err != 4 ) { fprintf( stderr, "comedi_command_test returned %d\n", err ); dump_cmd(stdout,&cmd); exit(1); } err = comedi_command_test(dev, &cmd); if (err > 0 && err != 4 ) { fprintf( stderr, "comedi_command_test returned %d\n", err ); dump_cmd(stdout,&cmd); exit(1); } dump_cmd(stderr,&cmd); /* init data buffer: */ data = (sampl_t *)malloc( fn*sizeof( sampl_t ) ); if(data == NULL ){ perror("malloc\n"); exit(1); } fprintf( stderr, "execute command ...\n" ); if ((err = comedi_command(dev, &cmd)) < 0) { comedi_perror("comedi_command"); exit(1); } fprintf( stderr, "start analog input ...\n" ); ret = comedi_internal_trigger(dev, options.subdevice, 0); if(ret < 0){ perror("comedi_internal_trigger\n"); exit(1); } n = 0; while( 1 ) { m = read(comedi_fileno(dev),(void *)data,fn*sizeof( sampl_t)); if(m<0){ if ( errno != EAGAIN ) { perror("read"); exit(0); } else { fprintf( stderr, "... no more data can be read! Try later.\n" ); usleep( 100000 ); } } else { m /= sizeof( sampl_t); fprintf( stderr, "read %d samples\n",m); n+=m; } } comedi_cancel( dev, cmd.subdev ); fprintf( stderr, "finished\n" ); /* save data: */ dp = data; for ( k=0; k<n; k++ ) { v = comedi_to_phys(*dp, rng, maxdata); printf( "%g\n", v ); /* printf( "%d\n", *dp );*/ ++dp; } free( data ); comedi_close( dev ); 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 long dsetInit_devAoSyncComedi (aoRecord *pao) { CONTEXT *p_myContext; COMEDIDEV_AO *p_myAnalogOutput; int myPinNumber; int myMinorOfDeviceFile; double myMinimumVoltage; double myMaximumVoltage; int myDifferentialMode; char p_myWarmstartFilename[BUFLEN]; FILE *p_myFileHandle; packageInfo(); dsetLog(3, __FILE__ "[%d] -> %s(%s)\n", __LINE__, __func__, pao->name ); p_myAnalogOutput=(COMEDIDEV_AO *)calloc(1, sizeof(COMEDIDEV_AO)); if ( sscanf(pao->out.value.instio.string, "modf=%d pn=%d dm=%d", &myMinorOfDeviceFile, &myPinNumber, &myDifferentialMode) != 3) { dsetLog(1, __FILE__ "[%d] Error: %s\n", __LINE__, pao->name); dsetLog(1, __FILE__ "[%d] Error: Couldn't parse parameters\n", __LINE__); dsetLog(1, __FILE__ "[%d] Error: >%s<\n", __LINE__,pao->out.value.instio.string); sleep(SLEEPTIME_ERROR); return(ERROR); } p_myAnalogOutput->aref=myDifferentialMode+1; /* always 2 ! */ sprintf(p_myAnalogOutput->p_deviceFilename,"/dev/comedi%d", myMinorOfDeviceFile); p_myAnalogOutput->device=comedi_open(p_myAnalogOutput->p_deviceFilename); p_myAnalogOutput->subdevice=0; p_myAnalogOutput->channel=(myPinNumber-1)/2; /* Get some values from the drivers */ p_myAnalogOutput->maxdata=comedi_get_maxdata(p_myAnalogOutput->device, p_myAnalogOutput->subdevice, p_myAnalogOutput->channel); myMinimumVoltage=pao->drvl; myMaximumVoltage=pao->drvh; p_myAnalogOutput->range=getOptimalOperatingRange(pao); p_myAnalogOutput->c_range=comedi_get_range(p_myAnalogOutput->device, p_myAnalogOutput->subdevice, p_myAnalogOutput->channel, p_myAnalogOutput->range); dsetLog(5,__FILE__ "[%d] Parsed options >%s<\n", __LINE__, pao->out.value.instio.string); dsetLog(5,__FILE__ "[%d] p_deviceFilename = >%s<\n", __LINE__, p_myAnalogOutput->p_deviceFilename); dsetLog(5,__FILE__ "[%d] subdevice = %d\n", __LINE__, p_myAnalogOutput->subdevice); dsetLog(5,__FILE__ "[%d] channel = %d\n", __LINE__, p_myAnalogOutput->channel); dsetLog(5,__FILE__ "[%d] range = %d\n", __LINE__, p_myAnalogOutput->range); dsetLog(5,__FILE__ "[%d] aref = %d\n", __LINE__, p_myAnalogOutput->aref); p_myContext=(CONTEXT *)calloc(1,sizeof(CONTEXT)); p_myContext->p_analogOutput=p_myAnalogOutput; p_myContext->minimumVoltage=myMinimumVoltage; p_myContext->maximumVoltage=myMaximumVoltage; sprintf(p_myWarmstartFilename, WARMSTART_FILE_PREFIX "/%s", pao->name); p_myFileHandle=fopen(p_myWarmstartFilename, "r"); if (p_myFileHandle!=NULL) { fscanf(p_myFileHandle, "%lg", &pao->val); fclose(p_myFileHandle); dsetLog(5, __FILE__ "[%d] Warmstart: %lg (File) -> %s\n", __LINE__, pao->val, pao->name); } else { dsetLog(5, __FILE__ "[%d] Warmstart: %lg (Default) -> %s\n", __LINE__, pao->val , pao->name); } pao->pini=menuYesNoYES; pao->dpvt=(void *)p_myContext; dsetLog(5, __FILE__ "[%d] Calibration algo : %d\n", __LINE__, pao->linr); dsetLog(5, __FILE__ "[%d] Calibration slope : %lg\n", __LINE__, pao->aslo); dsetLog(5, __FILE__ "[%d] Calibration offset: %lg\n", __LINE__, pao->aoff); dsetLog(3, __FILE__ "[%d] <- %s\n", __LINE__, __func__ ); /* Convert according to calibration? NO!*/ /* Convert update val based on rval and in iwarmstart file is stored val*/ return(DO_NOT_CONVERT); }
static int configBoard( int board ) { MY_BOARD_HARDWARE *pBoardHard = myBoard_getHardwareBoard( board ); MY_BOARD_SOFTWARE *pBoardSoft = myBoard_getSoftwareBoard( board ); if (pBoardHard == NULL || pBoardSoft == NULL) return -1; comedi_insn insn; lsampl_t p_insn_data[3]; int i; int status; insn.insn = INSN_CONFIG; insn.data = p_insn_data; insn.subdev = pBoardHard->subDeviceNumber; insn.n = 2; insn.data[0] = INSN_CONFIG_BLOCK_SIZE; insn.data[1] = 256; for(i=0; i < pBoardSoft->numberOfActiveAnalogInputs; i++){ int indexRange = pBoardHard->channelIndexRange[i]; insn.chanspec=CR_PACK( i, indexRange, pBoardHard->analogReference ); status = comedi_do_insn( pBoardHard->p_comediFileHandle, &insn ); if (status<0) { fprintf( stderr, "failed do inst for board[%d]\n", board ); return -1; } } if (pBoardHard->maxDataIsChannelSpecific || pBoardHard->rangeIsChannelSpecific) { for(i=0; i < pBoardSoft->numberOfActiveAnalogInputs; i++){ const comedi_range *pVoltageRange = comedi_get_range( pBoardHard->p_comediFileHandle, pBoardHard->subDeviceNumber, i, pBoardHard->channelIndexRange[i] ); int rawMax = comedi_get_maxdata( pBoardHard->p_comediFileHandle, pBoardHard->subDeviceNumber, i ); pBoardHard->channelRawToVoltA[i] = (pVoltageRange->max - pVoltageRange->min) / rawMax; pBoardHard->channelRawToVoltB[i] = pVoltageRange->min; fprintf( stderr, "set convert CONST for board[%d] channel[%d] a=%lf b=%lf\n", board, i, pBoardHard->channelRawToVoltA[i], pBoardHard->channelRawToVoltB[i] ); }/* for channel */ } else { const comedi_range *pVoltageRange = comedi_get_range( pBoardHard->p_comediFileHandle, pBoardHard->subDeviceNumber, 0, pBoardHard->channelIndexRange[0] ); int rawMax = comedi_get_maxdata( pBoardHard->p_comediFileHandle, pBoardHard->subDeviceNumber, 0 ); double rawToVoltA = (pVoltageRange->max - pVoltageRange->min) / rawMax; double rawToVoltB = pVoltageRange->min; fprintf( stderr, "set convert CONST for all channel on board[%d] a=%lf b=%lf\n", board, rawToVoltA, rawToVoltB ); for(i=0; i < pBoardSoft->numberOfActiveAnalogInputs; i++){ pBoardHard->channelRawToVoltA[i] = rawToVoltA; pBoardHard->channelRawToVoltB[i] = rawToVoltB; } } return 0; }
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; }
static int getOptimalRangeNumber( int board ) { MY_BOARD_HARDWARE *pBoardHard = myBoard_getHardwareBoard( board ); MY_BOARD_SOFTWARE *pBoardSoft = myBoard_getSoftwareBoard( board ); if (pBoardHard == NULL || pBoardSoft == NULL) return -1; int numRange; int indexRange; const comedi_range *pVoltageRange; if (pBoardHard->rangeIsChannelSpecific) { int chan; for (chan = 0; chan < pBoardSoft->numberOfActiveAnalogInputs; ++chan) { int found = 0; numRange = comedi_get_n_ranges( pBoardHard->p_comediFileHandle, pBoardHard->subDeviceNumber, chan ); for (indexRange = numRange - 1; indexRange >= 0; --indexRange) { pVoltageRange = comedi_get_range( pBoardHard->p_comediFileHandle, pBoardHard->subDeviceNumber, chan, indexRange ); if (pVoltageRange->min <= pBoardSoft->channelLopr[chan] && pVoltageRange->max >= pBoardSoft->channelHopr[chan]) { pBoardHard->channelIndexRange[chan] = indexRange; fprintf( stderr, "board[%d] chan[%d] set indexRange to %d\n", board, chan, indexRange ); found = 1; break; } }/*for range */ if (!found) { fprintf( stderr, "board[%d] chan[%d] no range good\n", board, chan ); pBoardHard->channelIndexRange[chan] = 0; } } /* for channel */ return 0; } else { numRange = comedi_get_n_ranges( pBoardHard->p_comediFileHandle, pBoardHard->subDeviceNumber, 0 ); fprintf( stderr, "board[%d] numRange=%d\n", board, numRange ); for (indexRange = numRange - 1; indexRange >= 0; --indexRange) { pVoltageRange = comedi_get_range( pBoardHard->p_comediFileHandle, pBoardHard->subDeviceNumber, 0, indexRange ); fprintf( stderr, "board[%d] VRange[%d]: min=%lf max=%lf\n", board, indexRange, pVoltageRange->min, pVoltageRange->max ); if (pVoltageRange->min <= pBoardSoft->lopr && pVoltageRange->max >= pBoardSoft->hopr) { fprintf( stderr, "board[%d] all channel set indexRange to %d\n", board, indexRange ); int chan; for (chan = 0; chan < pBoardSoft->numberOfActiveAnalogInputs; ++chan) { pBoardHard->channelIndexRange[chan] = indexRange; } return 0; } }/* for range */ fprintf( stderr, "failed to find range for lopr=%lf hopr=%lf\n", pBoardSoft->lopr, pBoardSoft->hopr ); return -1; } }