Esempio n. 1
0
File: sigio.c Progetto: jbetten/rtxi
void do_cmd(comedi_t *dev,comedi_cmd *cmd)
{
	int total=0;
	int ret;
	int go;

	ret=comedi_command_test(dev,cmd);

	printf("test ret=%d\n",ret);
	if(ret<0){
		printf("errno=%d\n",errno);
		comedi_perror("comedi_command_test");
		return;
	}

	dump_cmd(stdout,cmd);

	ret=comedi_command_test(dev,cmd);

	printf("test ret=%d\n",ret);
	if(ret<0){
		printf("errno=%d\n",errno);
		comedi_perror("comedi_command_test");
		return;
	}

	dump_cmd(stdout,cmd);

	ret=comedi_command(dev,cmd);

	printf("ret=%d\n",ret);
	if(ret<0){
		printf("errno=%d\n",errno);
		comedi_perror("comedi_command");
		return;
	}

	go=1;
	while(go){
		ret=read(comedi_fileno(dev),buf,BUFSZ);
		if(ret<0){
			if(errno==EAGAIN){
				printf("EAGAIN\n");
				usleep(10000);
			}else{
				go = 0;
				perror("read");
			}
		}else if(ret==0){
			go = 0;
		}else{
			//int i;

			total+=ret;
			//printf("read %d %d\n",ret,total);
			//printf("count = %d\n",count);
			//print_time();
		}
	}
}
Esempio n. 2
0
int main(int argc, char *argv[])
{
	lsampl_t data;
	int ret;
	struct parsed_options options;

	init_parsed_options(&options);
	parse_options(&options, argc, argv);

	device=comedi_open(options.filename);
	if(!device){
		comedi_perror(options.filename);
		exit(-1);
	}

	data = options.value;
	if(options.verbose){
		printf("writing %d to device=%s subdevice=%d channel=%d range=%d analog reference=%d\n",
			data, options.filename, options.subdevice, options.channel, options.range, options.aref);
	}

	ret = comedi_apply_calibration(device, options.subdevice, options.channel, options.range, options.aref, NULL);
	if(ret < 0){
		comedi_perror(options.filename);
		exit(0);
	}

	return 0;
}
Esempio n. 3
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;
}
Esempio n. 4
0
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
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
void internal_trigger() {
  ///assert(cmd!=NULL);

  //printf("triggering...");fflush(stdout);
  static comedi_insn ins[2];
  static comedi_insnlist il;
  lsampl_t d1, d2;
  int ret;
  il.n_insns=1;
  il.insns=ins;
  memset(ins, 0, 2*sizeof(comedi_insn));
  d1 = 0;
  d2 = 0;

  if(cmd && cmd->chanlist_len) {
    ins[0].insn=INSN_INTTRIG;
    ins[0].subdev=0;
    ins[0].data = &d1;
    ins[0].n = 1;
  }

  ret=comedi_do_insnlist(it,&il);
  if(ret<0){
    comedi_perror("error triggering ");
  }
  //printf("done\n");fflush(stdout);

}
Esempio n. 7
0
File: daq.c Progetto: nsaspook/mbmc
int init_dio(void)
{
	int i = 0;

	if (!DEV_OPEN) {
		it = comedi_open(comedi_dev);
		if (it == NULL) {
			comedi_perror("comedi_open");
			DIO_OPEN = FALSE;
			DEV_OPEN = FALSE;
			return -1;
		}
		DEV_OPEN = TRUE;
	}

	subdev_dio = comedi_find_subdevice_by_type(it, COMEDI_SUBD_DIO, subdev_dio);
	if (subdev_dio < 0) {
		return -1;
		DIO_OPEN = FALSE;
	}

	printf("Subdev  %i ", subdev_dio);
	channels_dio = comedi_get_n_channels(it, subdev_dio);
	printf("Digital Channels %i ", channels_dio);
	maxdata_dio = comedi_get_maxdata(it, subdev_dio, i);
	printf("Maxdata %i ", maxdata_dio);
	ranges_dio = comedi_get_n_ranges(it, subdev_dio, i);
	printf("Ranges %i \n", ranges_dio);
	DIO_OPEN = TRUE;
	return 0;
}
Esempio n. 8
0
static void dio_config( void )
{
	comedi_t *dev = lookup_dev( *sp++ );
	unsigned int subdev = *sp++;
	unsigned int chan = *sp++;
	unsigned int data = *sp++;
	int c = comedi_dio_config( dev, subdev, chan, data );
	if( c < 1 ) comedi_perror( "<dio> " );
}
Esempio n. 9
0
static void dio_read( void )
{
	comedi_t *dev = lookup_dev( *sp++ );
	unsigned int subdev = *sp++;
	unsigned int chan = *sp++;
	unsigned int data;
	int c = comedi_dio_read( dev, subdev, chan, &data );
	if( c < 1 ) comedi_perror( "@dio " );
	*--sp = data;
}
Esempio n. 10
0
bool ComediAnalogIO::openDevice()
{
        Logger(Debug, "ComediAnalogIO::openDevice()\n");
        m_device = comedi_open(m_deviceFile);
        if(m_device == NULL) {
                comedi_perror(m_deviceFile);
                return false;
        }
        return true;
}
Esempio n. 11
0
static void dio_bitfield( void )
{
	comedi_t *dev = lookup_dev( *sp++ );
	unsigned int subdev = *sp++;
	unsigned int mask = *sp++;
	unsigned int data = *sp++;
	int c = comedi_dio_bitfield( dev, subdev, mask, &data );
	if( c < 0 ) comedi_perror( "!@dio " );
	*--sp = data;
}
Esempio n. 12
0
static void data_write( void )
{
	comedi_t *dev = lookup_dev( *sp++ );
	unsigned int subdev = *sp++;
	unsigned int chan = *sp++;
	unsigned int range = *sp++;
	unsigned int aref = *sp++;
	lsampl_t data = *sp++;
	int c = comedi_data_write( dev, subdev, chan, range, aref, data );
	if( c < 1 ) comedi_perror( "!daq " );
}
Esempio n. 13
0
void ComediScope::startDAQ() {
	for(int devNo=0;devNo<nComediDevices;devNo++) {
		/* start the command */
		int ret=comedi_command(dev[devNo],cmd[devNo]);
		if(ret<0){
			comedi_perror("comedi_command");
			exit(1);
		}
	}
	startTimer( 50 );		// run continuous timer
	counter->start( 500 );
}
Esempio n. 14
0
static void data_read( void )
{
	comedi_t *dev = lookup_dev( *sp++ );
	unsigned int subdev = *sp++;
	unsigned int chan = *sp++;
	unsigned int range = *sp++;
	unsigned int aref = *sp++;
	lsampl_t data;
	int c = comedi_data_read( dev, subdev, chan, range, aref, &data );
	if( c < 1 ) comedi_perror( "@daq " );
	*--sp = data;
}
Esempio n. 15
0
int main(int argc, char *argv[])
{
	int retval;
	lsampl_t routing;
	struct parsed_options options;

	init_parsed_options(&options);
	options.freq = 0.;
	parse_options(&options, argc, argv);

	device = comedi_open(options.filename);
	if(!device){
		comedi_perror(options.filename);
		exit(-1);
	}
	routing = options.value;
	printf("Selecting routing %d for channel %d on subdevice %d.\n", routing, options.channel, options.subdevice);

	retval = comedi_set_routing(device, options.subdevice, options.channel, routing);
	if(retval < 0) comedi_perror("comedi_do_insn");
	return retval;
}
Esempio n. 16
0
int put_dio_bit(int chan, int bit_data) {
    lsampl_t data = bit_data;
    int retval;

    DIO_ERROR = FALSE;
    retval = comedi_data_write(it, subdev_dio, chan, range_dio, aref_dio, data);
    if (retval < 0) {
        comedi_perror("comedi_data_read in put_dio_bits");
        DIO_ERROR = TRUE;
        return -1;
    }
    return 0;
}
Esempio n. 17
0
double get_adc_volts(int chan) {
    lsampl_t data;
    int retval;

    ADC_ERROR = FALSE;
    retval = comedi_data_read_delayed(it, subdev_ai, chan, range_ai, aref_ai, &data, 10000);
    if (retval < 0) {
        comedi_perror("comedi_data_read in get_adc_volts");
        ADC_ERROR = TRUE;
        return 0.0;
    }
    return comedi_to_phys(data, ad_range, maxdata_ai);
}
Esempio n. 18
0
int set_dac_volts(int chan, double voltage) {
    lsampl_t data;
    int retval;

    DAC_ERROR = FALSE;
    data = comedi_from_phys(voltage, da_range, maxdata_ao);
    retval = comedi_data_write(it, subdev_ao, chan, range_ao, aref_ao, data);
    if (retval < 0) {
        comedi_perror("comedi_data_write in set_dac_volts");
        DAC_ERROR = TRUE;
    }
    return retval;
}
Esempio n. 19
0
int get_dio_bit(int chan) {
    lsampl_t data;
    int retval;

    DIO_ERROR = FALSE;
    retval = comedi_data_read(it, subdev_dio, chan, range_dio, aref_dio, &data);
    if (retval < 0) {
        comedi_perror("comedi_data_read in get_dio_bits");
        DIO_ERROR = TRUE;
        return 0;
    }
    if (data != 0) data = 1;
    return data;
}
Esempio n. 20
0
int main(int argc, char *argv[])
{
	int ret;
	int stype;
	struct parsed_options options;

	init_parsed_options(&options);
	parse_options(&options, argc, argv);

	device = comedi_open(options.filename);
	if(!device){
		comedi_perror(options.filename);
		exit(-1);
	}

	stype = comedi_get_subdevice_type(device, options.subdevice);
	if(stype != COMEDI_SUBD_DIO){
		printf("%d is not a digital I/O subdevice\n", options.subdevice);
		exit(-1);
	}

	printf("configuring pin %d on subdevice %d ", options.channel, options.subdevice);
	if(options.value)
	{
		printf("for output.\n");
		ret = comedi_dio_config(device, options.subdevice, options.channel, COMEDI_OUTPUT);
	}else
	{
		printf("for input.\n");
		ret = comedi_dio_config(device, options.subdevice, options.channel, COMEDI_INPUT);
	}
	if(ret < 0){
		comedi_perror("comedi_dio_config");
		exit(-1);
	}
	return 0;
}
Esempio n. 21
0
int main(int argc, char *argv[])
{
	unsigned period_ns;
	int retval;
	lsampl_t clock_selection;
	struct parsed_options options;

	init_parsed_options(&options);
	options.freq = 0.;
	parse_options(&options, argc, argv);

	device = comedi_open(options.filename);
	if(!device){
		comedi_perror(options.filename);
		exit(-1);
	}
	if(options.freq > 0.)
		period_ns = 1e9 / options.freq;
	else
		period_ns = 0;
	clock_selection = options.value;
	printf("Selecting master clock %d for channel %d on subdevice %d.\n", clock_selection, options.channel, options.subdevice);
	if(period_ns)
	{
		printf("Clock period = %d nanoseconds.\n", period_ns);
	}else
	{
		printf("Clock period unspecified.\n");
	}

	retval = comedi_set_clock_source(device, options.subdevice, options.channel, clock_selection, period_ns);
	if(retval < 0) comedi_perror("comedi_set_clock_source");

	comedi_close(device);
	return retval;
}
Esempio n. 22
0
static comedi_t *lookup_dev( unsigned dev )
{
	static char devname[] = "/dev/comedixx";
	
	if( dev >= 16 ) {
		fprintf( stderr, "Comedi device number %d too large.\n", dev );
		return NULL;
	}
	if( !devices[dev] ) {
		sprintf( devname, "/dev/comedi%u", dev );
		devices[dev] = comedi_open( devname );
		if( !devices[dev] ) comedi_perror( devname );
	}
	return devices[dev];
}
Esempio n. 23
0
bool ComediDigitalIO::openDevice()
{
        Logger(Debug, "ComediDigitalIO::openDevice()\n");
        m_device = comedi_open(m_deviceFile);
        if(m_device == NULL) {
                comedi_perror(m_deviceFile);
                return false;
        }
	if (comedi_get_subdevice_type(m_device, m_subdevice) != COMEDI_SUBD_DIO) {
		Logger(Critical, "ComediDigitalIO::openDevice() - Subdevice is not DIO.\n");
		if (!closeDevice())
			Logger(Critical, "ComediDigitalIO::openDevice() - Failed to close device.\n");
		return false;
	}
        return true;
}
Esempio n. 24
0
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);
}
Esempio n. 25
0
/*!
    \fn newViewDialog::slotPluginSelected()
 */
void newViewDialog::slotPluginSelected()
{
	QString name = pluginsList->currentItem()->text();
	okPushButton->setEnabled( TRUE );
	
	QListIterator<pluginData> it(pl);
	while( it.hasNext() ){
		pluginData data = it.next();
		if ( data.name == name ){
			maxSelect = data.numChannels;

            int comediSubdevice = comedi_find_subdevice_by_type(comediDevice,data.type_comedi,0);
            if( comediSubdevice >= 0){
                maxChannels = comedi_get_n_channels(comediDevice, comediSubdevice);
                okPushButton->setEnabled(TRUE);
                status->setText(QString("comedi subdevice\ntype %1 found!").arg(data.type_comedi));
            }
            else{
                //comedi_perror( QString("error in %1 line %2").arg(__func__).arg(__LINE__).toStdString().c_str() );
                okPushButton->setEnabled(FALSE);
                maxChannels = 0;
                status->setText(QString("comedi subdevice\ntype %1 not found!").arg(data.type_comedi));
            }

            if( maxChannels < 0 ){
                maxChannels = 0;
                comedi_perror( QString("error in %1 line %2").arg(__func__).arg(__LINE__).toStdString().c_str() );
            }

			if(channelSelectors.count() < maxSelect)
				for( int i = channelSelectors.count(); i < maxSelect; i++ ) {
					QSpinBox *spinBox = new QSpinBox();
					spinBox->setRange( 0, maxChannels-1 );
					channelsListL->addWidget( spinBox );
					
					channelSelectors << spinBox ;
				}
			else if(channelSelectors.count() > maxSelect) {
				channelSelectors.last();
				for( int i = maxSelect; i< channelSelectors.count(); i++ )
					 delete channelSelectors.takeLast();
			}
        }
	}
}
Esempio n. 26
0
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;

}
Esempio n. 27
0
int main(int argc, char *argv[])
{
	int ret;
	int stype;
	int i;
	struct parsed_options options;

	init_parsed_options(&options);
	options.subdevice = -1;
	parse_options(&options, argc, argv);

	device = comedi_open(options.filename);
	if(!device){
		comedi_perror(options.filename);
		exit(-1);
	}
	if(options.subdevice < 0)
	{
		options.subdevice = comedi_find_subdevice_by_type(device, COMEDI_SUBD_DIO, 0);
		if(options.subdevice < 0){
			fprintf(stderr,"No dio subdevice found.\n");
			exit(-1);
		}
	}
	stype = comedi_get_subdevice_type(device, options.subdevice);
	if(stype != COMEDI_SUBD_DIO){
		printf("%d is not a digital I/O subdevice\n", options.subdevice);
		exit(-1);
	}

	printf("configuring pin %d for output...\n", chan_dat);
	ret = comedi_dio_config(device, options.subdevice, chan_dat, COMEDI_OUTPUT);

	printf("configuring pin %d for output...\n", chan_clk);
	ret = comedi_dio_config(device, options.subdevice, chan_clk, COMEDI_OUTPUT);

	for(i = 0; i < 0x100; i++){
		write_bits(options.subdevice, i);
	}
	//write_bits(0xa5);

	return 0;
}
Esempio n. 28
0
File: daq.c Progetto: nsaspook/mbmc
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;
}
Esempio n. 29
0
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;
}
Esempio n. 30
0
File: daq.c Progetto: nsaspook/mbmc
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
}